1

I have array like bellow:

var array = [{name: 'abc', age: 17}, {name: 'cde', age: 20}, {name: 'abc', age: 89}]

I would like to have output like:

array = [{name: 'abc', age: [17, 89]}, {name: 'cde', age: 20}]

How can achieve it? I tried many solutions like eg:

var result = _(array)
      .groupBy('name')
      .map(_.spread(_.assign))
      .value();

but it's not what I want because I would like to have array of values age.

1
  • What is _ in the shared code? Is it underscore.js? Or lodash? Commented Mar 8, 2020 at 20:36

5 Answers 5

1

try this

const data  = [{name: 'abc', age: 17}, {name: 'cde', age: 20}, {name: 'abc', age: 89}]
         
const groupBy = (arr) => data.reduce((acc, ele)=>( (acc[ele.name] = acc[ele.name] || []).push(ele), acc),{})
const displayAge= v => v.length>1?v.map(e=>e.age):v[0].age

console.log(Object.entries(groupBy(data)).map(([name, v])=>({name, age: displayAge(v)})))

Sign up to request clarification or add additional context in comments.

Comments

1

You can create a map (which is constant time lookup), then convert it to an array. Not the prettiest solution, but definitely performant in terms of complexity (linear).

const array = [{name: 'abc', age: 17}, {name: 'cde', age: 20}, {name: 'abc', age: 89}]

const m = new Map();
array.map(x => {
    if (!m.has(x.name)) {
        m.set(x.name, []);
    }
    m.get(x.name).push(x.age);
});

console.log(Array.from(m).map(
    (x) => Object.assign({'name': x[0], 'age': x[1]})));

Comments

0

Well I don't understand why aren't you using loops or anything.. You didn't specify format so here have my code in vanila js:

var array = [{name: 'abc', age: 17}, {name: 'cde', age: 20}, {name: 'abc', age: 89}]

for (var i = 0; i < array.length; i++) {
  for (var j = i + 1; j < array.length; j++) {
    if (array[i].name == array[j].name) {
      if (Array.isArray(array[i].age)) {
        array[i].age.push(array[j].age)
      } else {
        var arAge = [array[i].age, array[j].age];
        array[i].age = arAge;
      }
      array.splice(j,1);
      j--;
    }
  }
}

Comments

0

What about:

var result = array.forEach(a => {
    let similar = array.filter(b => b.name == a.name).map(c => c.age);
    a.age = similar.length > 1 ? similar : a.age;
}).filter((d,e) => array.indexOf(d) == e);

Comments

0

Would be easier if you always kept age as an array instead of being Number when only one value is present.

const array = [{name: 'abc', age: 17}, {name: 'cde', age: 20}, {name: 'abc', age: 89}]
const newArray = array.reduce((arr, i) => {
    const inArray = arr.findIndex(a => a.name === i.name);
    if (inArray < 0) arr.push(i);
    else {
        if (Array.isArray(arr[inArray].age)) {
            arr[inArray].age.push(i.age);
        } else {
            arr[inArray].age = [arr[inArray].age, i.age];
        }
    }
    return arr;
}, [])

console.log(newArray);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.