Home > Blockchain >  An array of objects is returned to me. How to return an array of objects where only the unique group
An array of objects is returned to me. How to return an array of objects where only the unique group

Time:01-25

[
{"score": 99, "group":"1"},
{"score": 90, "group":"2"},
{"score":"10", "group":"1"},
{"score":"10",      "group":"2"},
]
 

I work with TypeOrm now and want to filter data.

Expected array:

[
{"score": 99,      "group":"1"},
{"score": 90,     "group":"2"},
]

CodePudding user response:

const data = [
{"score": 99, "group":"1"},
{"score": 90, "group":"2"},
{"score": 10, "group":"1"},
{"score": 10, "group":"2"}]

const result = [...new Set(data.map(i=>i.group))] // get unique group ids
  .map(g=>data.filter(({group})=>g===group) // find members of each group 
  .sort(({score:a},{score:b})=>a-b).pop()) // find the one with highest score

console.log(result)

If your data includes scores that are strings instead of numbers, change a-b to ( a)-( b) to coerce the strings to numbers.

CodePudding user response:

I would use Lodash in this case

function maxGroups() {
let arr = [
    {"score": 99, "group":"1"},
    {"score": 90, "group":"2"},
    {"score": 10, "group":"1"},
    {"score": 10, "group":"2"},
]

let newArr = _.groupBy(arr, "group")
let result = _.map(newArr, i => (_.maxBy(i, 'score')));
console.dir(result)

}

CodePudding user response:

You could take a single loop approach with an object for keeping the groups.

const
    data = [{ score: 99, group: "1" }, { score: 90, group: "2" }, { score: 10, group: "1" }, { score: 10, group: "2" }],
    maxScore = Object.values(data.reduce((r, o) => {
        if (!r[o.group] || r[o.group].score < o.score) r[o.group] = o;
        return r;
    }, {}));
    
console.log(maxScore);
.as-console-wrapper { max-height: 100% !important; top: 0; }

CodePudding user response:

You can simply group by group keeping only the objects with the highest score. Here accumulating into a Map and then spreading the iterator returned by Map.values() as the result.

const input = [{ score: 99, group: '1' }, { score: 90, group: '2' }, { score: '10', group: '1' }, { score: '10', group: '2' },];

const reduced = input.reduce(
  (a, o) =>
    !a.has(o.group) || o.score > a.get(o.group)?.score
      ? a.set(o.group, { ...o })
      : a,
  new Map()
);

const result = [...reduced.values()];

console.log(result);

CodePudding user response:

For fun, here is another version:

const data = [
    {"score": 99, "group":"1"},
    {"score": 90, "group":"2"},
    {"score": 10, "group":"1"},
    {"score": 10, "group":"2"},
]

const maxByGroup = {}
for(const entry of data){
  const max = maxByGroup[entry.group]
  maxByGroup[entry.group] = max && max.score >= entry.score ? max : entry
}
const result = Object.values(maxByGroup)

console.log(result)

Probably the simplest way to do it, arguably the easiest to read, happens to be the fastest, too

  • Related