BaiClassmate Xiao
BaiClassmate Xiao

Reputation: 381

JavaScript: How to add and sort the same fields in an array based on fields?

I have the following array a as shown below:

var a = [
  {name: 'phone' , id:1 ,num:1},
  {name: 'milk' ,id:2, num:1},
  {name: 'apple' , id:3 , num:1},
  {name: 'phone', id: 4, num:3},
]

I want to filter by array name and add their own num

var currentName = a[0]
let newArrys=[]
for(let i = 0; i<a.length;i++){
   if(currentName.name == a[i].name){
       a[i].num = a[i].num + currentName.num
       let tmepArry = [];
        tempArry.push(a[i]);
        newArrys.push(tempArry);
   }
}

I am trying to obtain the following 2D array:

[
 [{name: 'phone', id:1, num:4}],
 [{name: 'milk',id:2, num:1}],
 [{name: 'apple', id: 3 num:1}]
]

The result cannot be screened out.

My attempt is invalid.

Can you help me?

Upvotes: 4

Views: 94

Answers (3)

Norman
Norman

Reputation: 387

Not sure if this is the best solution but it does work. Please feel free to give advise on what I should have done instead for a better code. Haha..

var a = [
  {name: 'phone' , id:1 ,num:1},
  {name: 'milk' ,id:2, num:1},
  {name: 'apple' , id:3 , num:1},
  {name: 'phone', id: 4, num:3},
]

function organize_array(tmpArray) {
  let data = []
  tmpArray.forEach(function(value, key) {
      if(data.filter(tmp => tmp.name == value.name) == '') {
        const tmpFiltered = a.filter(tmp => tmp.name == value.name)
        let total = 0
        tmpFiltered.map(x => { total += x.num })
        data.push({name: value.name, num: total})
      }
  })
  return data
}

console.log(organize_array(a))

Upvotes: 0

mwilson
mwilson

Reputation: 12900

Here's a quick example of how to go about it. Essentially it's a two step process that involves first reducing your array of objects into a distinct list with the counts (num). Then, iterating over your results to create your 2D array.

There's probably a fancier way to produce the same result by adding a little bit more code to the reducer, but trying to go for readability here as it's rather easy to get lost in reduce functions.

var a = [
  {name: 'phone' , id:1 ,num:1},
  {name: 'milk' ,id:2, num:1},
  {name: 'apple' , id:3 , num:1},
  {name: 'phone', id: 4, num:3},
]

// Get the counts using reduce
const results = a.reduce( (acc, curr) => {
	if (acc.hasOwnProperty(curr.name)) {
  	acc[curr.name].num += curr.num;
  } else {
  	acc[curr.name] = {id: curr.id, num: curr.num };
  }
  return acc;
}, {});

// Establish result array
const finalResult = [];
// Iterate over results object and format them into an array of a single object
// then push the array to the finalResult array (thus making it 2D)
for (const key in results) {
	const item = results[key];
	finalResult.push([{ name: key, id: item.id, num: item.num }]);
}

console.log(finalResult);

Upvotes: 1

Scott Powell
Scott Powell

Reputation: 422

Given:

var a = [
  {name: 'phone' , id:1 ,num:1},
  {name: 'milk' ,id:2, num:1},
  {name: 'apple' , id:3 , num:1},
  {name: 'phone', id: 4, num:3},
]
const newArrys = a.reduce((acc, current) => {
  // find an object in the array with a matching name
  const existing = acc.find(obj => obj.name === current.name);
  if (existing) {
    // combine the numbers
    existing.num += current.num;
  } else {
    acc.push(current);
  }
  return acc;
}, []).map(obj => [obj])

That will get you what you need.

Upvotes: 3

Related Questions