按最小对象值区分对象数组
Distinct array of objects by smallest object value
我有一个对象数组:
[{Name: "Company 1", AddressName: "Address 1", Radius: "5000" },
{Name: "Company 1", AddressName: "Address 1", Radius: "2000" },
{Name: "Company 1", AddressName: "Address 1", Radius: "500" },
{Name: "Company 2", AddressName: "Address 2", Radius: "500" },
{Name: "Company 3", AddressName: "Address 3", Radius: "3000" },
...]
有些公司可以出现在不同的半径内,所以在阵列中它们会出现多次。
我要的是:如果同名同地址的公司在数组中多次出现,只保留半径最小的公司:
[{Name: "Company 1", AddressName: "Address 1", Radius: "500" },
{Name: "Company 2", AddressName: "Address 2", Radius: "500" },
{Name: "Company 3", AddressName: "Address 3", Radius: "3000" },
...]
const arr = [
{Name: "Company 1", AddressName: "Address 1", Radius: "5000" },
{Name: "Company 1", AddressName: "Address 1", Radius: "2000" },
{Name: "Company 1", AddressName: "Address 1", Radius: "500" },
{Name: "Company 2", AddressName: "Address 2", Radius: "500" },
{Name: "Company 3", AddressName: "Address 3", Radius: "3000" },
];
const res = arr.sort((a, b) => +a.Radius - +b.Radius)
.filter((a, i) => arr.findIndex((b) => a.Name === b.Name && a.AddressName === b.AddressName) === i);
console.log(res);
没有提前排序的解决方案。
基本上,您需要按 Name
进行分组,并通过最小化每个组的 Radius
进行额外过滤。
此方法尝试查找同一组的索引,如果找不到index === -1
,它会将实际对象推送到结果集中。
否则如果存储对象Radius
的数值大于实际对象,则将结果集中的对象替换为实际对象
var data = [{ Name: "Company 1", AddressName: "Address 1", Radius: "5000" }, { Name: "Company 1", AddressName: "Address 1", Radius: "2000" }, { Name: "Company 1", AddressName: "Address 1", Radius: "500" }, { Name: "Company 2", AddressName: "Address 2", Radius: "500" }, { Name: "Company 3", AddressName: "Address 3", Radius: "3000" }],
result = data.reduce((r, o) => {
var index = r.findIndex(q => q.Name === o.Name);
if (index === -1) r.push(o);
else if (+r[index].Radius > +o.Radius) r[index] = o;
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
如果你想让它更实用并且松散地基于 SQL,比如下面的查询,
SELECT Name, AddressName, MIN(Radius)
FROM data
GROUP BY Name;
您可以先分组,然后从结果集中取出最小对象。
result = pipe(
groupBy('Name'),
select(max('Radius'))
)(data);
const
pipe = (...functions) => input => functions.reduce((acc, fn) => fn(acc), input),
groupBy = key => array => array.reduce((r, o) => {
var temp = r.find(([p]) => o[key] === p[key])
if (temp) temp.push(o);
else r.push([o]);
return r;
}, []),
min = key => array => array.reduce((a, b) => +a[key] < +b[key] ? a : b),
select = fn => array => array.map(fn);
var data = [{ Name: "Company 1", AddressName: "Address 1", Radius: "5000" }, { Name: "Company 1", AddressName: "Address 1", Radius: "2000" }, { Name: "Company 1", AddressName: "Address 1", Radius: "500" }, { Name: "Company 2", AddressName: "Address 2", Radius: "500" }, { Name: "Company 3", AddressName: "Address 3", Radius: "3000" }],
result = pipe(
groupBy('Name'),
select(min('Radius'))
)(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
从@ponury-cubes 中汲取灵感,
// this will return object
var c = test.sort((a,b) => +b.Radius - +a.Radius).reduce((a,d)=>{
a[`${d.Name}:${d.AddressName}`] = d;
return a;
},{});
// this will convert to array of objects
var res = Object.keys(c).reduce((a,d)=>{
a.push(c[`${d}`]);
return a;
},[]);
我有一个对象数组:
[{Name: "Company 1", AddressName: "Address 1", Radius: "5000" },
{Name: "Company 1", AddressName: "Address 1", Radius: "2000" },
{Name: "Company 1", AddressName: "Address 1", Radius: "500" },
{Name: "Company 2", AddressName: "Address 2", Radius: "500" },
{Name: "Company 3", AddressName: "Address 3", Radius: "3000" },
...]
有些公司可以出现在不同的半径内,所以在阵列中它们会出现多次。
我要的是:如果同名同地址的公司在数组中多次出现,只保留半径最小的公司:
[{Name: "Company 1", AddressName: "Address 1", Radius: "500" },
{Name: "Company 2", AddressName: "Address 2", Radius: "500" },
{Name: "Company 3", AddressName: "Address 3", Radius: "3000" },
...]
const arr = [
{Name: "Company 1", AddressName: "Address 1", Radius: "5000" },
{Name: "Company 1", AddressName: "Address 1", Radius: "2000" },
{Name: "Company 1", AddressName: "Address 1", Radius: "500" },
{Name: "Company 2", AddressName: "Address 2", Radius: "500" },
{Name: "Company 3", AddressName: "Address 3", Radius: "3000" },
];
const res = arr.sort((a, b) => +a.Radius - +b.Radius)
.filter((a, i) => arr.findIndex((b) => a.Name === b.Name && a.AddressName === b.AddressName) === i);
console.log(res);
没有提前排序的解决方案。
基本上,您需要按 Name
进行分组,并通过最小化每个组的 Radius
进行额外过滤。
此方法尝试查找同一组的索引,如果找不到index === -1
,它会将实际对象推送到结果集中。
否则如果存储对象Radius
的数值大于实际对象,则将结果集中的对象替换为实际对象
var data = [{ Name: "Company 1", AddressName: "Address 1", Radius: "5000" }, { Name: "Company 1", AddressName: "Address 1", Radius: "2000" }, { Name: "Company 1", AddressName: "Address 1", Radius: "500" }, { Name: "Company 2", AddressName: "Address 2", Radius: "500" }, { Name: "Company 3", AddressName: "Address 3", Radius: "3000" }],
result = data.reduce((r, o) => {
var index = r.findIndex(q => q.Name === o.Name);
if (index === -1) r.push(o);
else if (+r[index].Radius > +o.Radius) r[index] = o;
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
如果你想让它更实用并且松散地基于 SQL,比如下面的查询,
SELECT Name, AddressName, MIN(Radius)
FROM data
GROUP BY Name;
您可以先分组,然后从结果集中取出最小对象。
result = pipe(
groupBy('Name'),
select(max('Radius'))
)(data);
const
pipe = (...functions) => input => functions.reduce((acc, fn) => fn(acc), input),
groupBy = key => array => array.reduce((r, o) => {
var temp = r.find(([p]) => o[key] === p[key])
if (temp) temp.push(o);
else r.push([o]);
return r;
}, []),
min = key => array => array.reduce((a, b) => +a[key] < +b[key] ? a : b),
select = fn => array => array.map(fn);
var data = [{ Name: "Company 1", AddressName: "Address 1", Radius: "5000" }, { Name: "Company 1", AddressName: "Address 1", Radius: "2000" }, { Name: "Company 1", AddressName: "Address 1", Radius: "500" }, { Name: "Company 2", AddressName: "Address 2", Radius: "500" }, { Name: "Company 3", AddressName: "Address 3", Radius: "3000" }],
result = pipe(
groupBy('Name'),
select(min('Radius'))
)(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
从@ponury-cubes 中汲取灵感,
// this will return object
var c = test.sort((a,b) => +b.Radius - +a.Radius).reduce((a,d)=>{
a[`${d.Name}:${d.AddressName}`] = d;
return a;
},{});
// this will convert to array of objects
var res = Object.keys(c).reduce((a,d)=>{
a.push(c[`${d}`]);
return a;
},[]);