Group array multiple item in another array

Viewed 48

This is my Array:

    myArray = [
        {group: "one", version: 1.1, old: 0.1},
        {group: "two", version: 2.1, old: 1.1},
        {group: "one", version: 1.2, old: 0.2},
        {group: "one", version: 1.3, old: 0.3}
    ]

I want to convert into this (need to retrieve only the bigger and smaller version) :

myArray = [
 {group: "one", recentVersion: 1.3, oldVersion:0.1 }
 {group: "two", recentVersion: 2.1, oldVersion:1.1}
 ]

What I'm trying:

const groups = {};
    for (let i = 0; i < myArray.length; i++) {
        const groupName = diffList[i].group;
        if (!groups[groupName]) {
            groups[groupName] = [];
        }
        groups[groupName].push(diffList[i].version);
    }
    const myArray = [];
    for (const groupName in groups) {
        myArray.push({ group: groupName, recentVersion: groups[groupName});
    }
    console.log(myArray);

Actual result :

myArray = [
 {group: "one", recentVersion: [1.1,1.2,1.3]}
 {group: "two", recentVersion: [2.2]}
 ]

I don't know how to retrieve the bigger and smaller version and how push oldVersion...

5 Answers

Repl Example

This example first aggregates all versions by group name, then it sorts the versions from old-to-new and returns an array with the newest and oldest object properties.

myArray = myArray
.reduce((_myArray, arrayItem) => {
  _myArray[arrayItem.group] = _myArray[arrayItem.group] || []
  _myArray[arrayItem.group].push(arrayItem.version, arrayItem.old)
  return _myArray
}, {})
myArray = Object.entries(myArray)
.reduce((_myArray, [groupName, groupVersions]) => {
  groupVersions = groupVersions
  .sort((current, next) => current > next ? -1 : 1)
  _myArray.push({
    group: groupName,
    recentVersion: groupVersions[0],
    oldVersion: groupVersions[groupVersions.length - 1],
  })
  return _myArray
}, [])

You could group the data and update the versions, if necessary.

var data = [{ group: "one", version: 1.1, old: 0.1 }, { group: "two", version: 2.1, old: 1.1 }, { group: "one", version: 1.2, old: 0.2 }, { group: "one", version: 1.3, old: 0.3 }],
    grouped = Object.values(data.reduce((r, { group, version, old }) => {
        if (!r[group]) {
            r[group] = { group, recentVersion: version, oldVersion: old };
            return r;
        }
        if (r[group].recentVersion < version) r[group].recentVersion = version;
        if (r[group].oldVersion > old) r[group].oldVersion = old;
        return r;
    }, {}));
    
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

You can do this using Array#reduce. I like using a map to lookup the groups by name instead of needing to search the array repeatedly. You can use Math.min and Math.max to set the correct recentVersion and oldVersion.

const myArray = [
        {group: "one", version: 1.1, old: 0.1},
        {group: "two", version: 2.1, old: 1.1},
        {group: "one", version: 1.2, old: 0.2},
        {group: "one", version: 1.3, old: 0.3}
    ];

const result = myArray.reduce((acc,{group,version,old}) => {
  let cur = acc[0][group];
  if(!cur) acc.push(cur = acc[0][group] = {group});
  cur.recentVersion = Math.max(version, cur.recentVersion || version);
  cur.oldVersion = Math.min(old, cur.oldVersion || old);
  return acc;
}, [{}]).slice(1);

console.log(result);

You could set the old and recent version every time by comparing in the first for loop

let diffList = [
  { group: "one", version: 1.1, old: 0.1 },
  { group: "two", version: 2.1, old: 1.1 },
  { group: "one", version: 1.2, old: 0.2 },
  { group: "one", version: 1.3, old: 0.3 }
];
const groups = {};
for (let i = 0; i < diffList.length; i++) {
  const groupName = diffList[i].group;
  if (!groups[groupName]) {
    groups[groupName] = {
      recentVersion: diffList[i].version,
      oldVersion: diffList[i].old
    };
  }
  if (groups[groupName].recentVersion < diffList[i].version) {
    groups[groupName].recentVersion = diffList[i].version;
  }
  if (groups[groupName].oldVersion > diffList[i].old) {
    groups[groupName].oldVersion = diffList[i].version;
  }
}
let myArray = [];
for (const groupName in groups) {
  myArray.push({
    group: groupName,
    recentVersion: groups[groupName].recentVersion,
    oldVersion: groups[groupName].oldVersion
  });
}
console.log(myArray);

I have edited the code written by you and incorporated the changes required to accomplish the required task. Please find the code below:

myArray = [{
    group: "one",
    version: 1.1,
    old: 0.1
  },
  {
    group: "two",
    version: 2.1,
    old: 1.1
  },
  {
    group: "one",
    version: 1.2,
    old: 0.2
  },
  {
    group: "one",
    version: 1.3,
    old: 0.3
  }
]

const group = {};
const results = [];
for (let i = 0; i < myArray.length; i++) {
  const element = myArray[i];
  if (!group[element.group]) {
    group[element.group] = true;
    results.push({
      group: element.group,
      recentVersion: element.version,
      oldVersion: element.old
    })
  } else {
    const index = results.findIndex((d) => d.group === element.group);
    if (element.version > results[index].recentVersion) {
      results[index].recentVersion = element.version;
    }
    if (element.old < results[index].oldVersion) {
      results[index].oldVersion = element.old;
    }
  }
}

console.log(results);

Related