Различный массив объектов по наименьшему значению объекта - PullRequest
0 голосов
/ 23 октября 2019

У меня есть массив объектов:

    [{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" },
    ...]

Ответы [ 3 ]

4 голосов
/ 23 октября 2019

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);
1 голос
/ 23 октября 2019

Решение без предварительной сортировки.


Как правило, вам нужно группировать по 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;

Вы можете сгруппировать сначала и взять объект min из результирующих наборов.

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; }
0 голосов
/ 23 октября 2019

Вдохновение от @ ponury-kostek,

// 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;
    },[]);
...