Tony Hensler
Tony Hensler

Reputation: 1492

JS Loop through array based on key values and add values

I have the following object inside an array:-

[
 {"score": 5, "question": 0, "weight": 2},
 {"score": 4, "question": 1, "weight": 2},
 {"score": 3, "question": 0, "weight": 4},
 {"score": 4, "question": 1, "weight": 4},
 {"score": 2, "question": 2, "weight": 4},
 {"score": 8, "question": 0, "weight": 2}
]

I am trying to loop through the array so I have the following output, so I am able to run some math against the results:-

[
  [
    {"score": 5, "question": 0, "weight": 2},
    {"score": 4, "question": 1, "weight": 2}
  ],
  [
    {"score": 3, "question": 0, "weight": 4},
    {"score": 4, "question": 1, "weight": 4},
    {"score": 2, "question": 2, "weight": 4}
  ],
  [
    {"score": 8, "question": 0, "weight": 2}
  ]
];

Is there a dynamic way I am able to get array1 to look like array2?

I am using flat JS for this please no jQuery answers.

Thanks in advance.

** Note **

Sometimes each section will have more or less values, this is why I require it to be dynamic.

Upvotes: 1

Views: 56

Answers (7)

Slai
Slai

Reputation: 22866

A bit simplified if splitting by just question: 0 :

data = [ { score: 5, question: 0, weight: 2 }, { score: 4, question: 1, weight: 2 },
         { score: 3, question: 0, weight: 4 }, { score: 4, question: 1, weight: 4 },
         { score: 2, question: 2, weight: 4 }, { score: 8, question: 0, weight: 2 } ]

result = data.reduce((r, v) => (v.question ? r[r.length-1].push(v) : r.push([v]), r), [])

console.log( result )

Upvotes: 0

connexo
connexo

Reputation: 56744

let scores = [
 {"score": 5, "question": 0, "weight": 2},
 {"score": 4, "question": 1, "weight": 2},
 {"score": 3, "question": 0, "weight": 4},
 {"score": 4, "question": 1, "weight": 4},
 {"score": 2, "question": 2, "weight": 4},
 {"score": 8, "question": 0, "weight": 2}
]

let groupedScores = [], group = [];

scores.forEach((entry) => {
  if(entry.question === 0) { 
    if (group.length) { 
      groupedScores.push(group); 
    }
    group = []; 
  }
  group.push(entry);
})
groupedScores.push(group)

console.log(groupedScores)

Upvotes: 0

Hassan Imam
Hassan Imam

Reputation: 22524

You can use array#reduce to group your array. Check if the value of question is 0 then push a new array and add the object to it.

var data = [ {"score": 5, "question": 0, "weight": 2}, {"score": 4, "question": 1, "weight": 2}, {"score": 3, "question": 0, "weight": 4}, {"score": 4, "question": 1, "weight": 4}, {"score": 2, "question": 2, "weight": 4}, {"score": 8, "question": 0, "weight": 2}],
    result = data.reduce((r,o) => {
      if(o.question == 0)
        r.push([]);
      r[r.length - 1].push(o);
      return r;
    },[]);
console.log(result);

Upvotes: 0

Igor
Igor

Reputation: 15893

var oldA = [
 {"score": 5, "question": 0, "weight": 2},
 {"score": 4, "question": 1, "weight": 2},
 {"score": 3, "question": 0, "weight": 4},
 {"score": 4, "question": 1, "weight": 4},
 {"score": 2, "question": 2, "weight": 4},
 {"score": 8, "question": 0, "weight": 2}
];

var newA = [];
var prevW = 0;
var prevA;

for (var i = 0; i < oldA.length; i++) {
  if (oldA[i].weight != prevW) {
    prevA = [];
    newA.push(prevA);
    prevW = oldA[i].weight;
  }
  prevA.push(oldA[i]);
}

console.log(newA);

Upvotes: 0

Ori Drori
Ori Drori

Reputation: 191976

You can use Array.reduce() to convert the 1st to the 2nd array. Whenever the current object weight doesn't match lastWeight, add another subarray. Always push the current item to the last subarray:

const arr = [
  {score: 5, question: 0, weight: 2},
  {score: 4, question: 1, weight: 2},
  {score: 3, question: 0, weight: 4},
  {score: 4, question: 1, weight: 4},
  {score: 2, question: 2, weight: 4},
  {score: 8, question: 0, weight: 2}
];

let lastWeight = null;
const result = arr.reduce((r, o) => {
  if(lastWeight === null || o.weight !== lastWeight) {
    lastWeight = o.weight;
    r.push([]);
  }
  r[r.length - 1].push(o);
  
  return r;
}, []);

console.log(result);

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386560

You could check weight and if different, then take a new group.

var data = [{ score: 5, question: 0, weight: 2 }, { score: 4, question: 1, weight: 2 }, { score: 3, question: 0, weight: 4 }, { score: 4, question: 1, weight: 4 }, { score: 2, question: 2, weight: 4 }, { score: 8, question: 0, weight: 2 }],
    grouped = data.reduce(function (r, o, i, a) {
        if ((a[i - 1] || {}).weight !== o.weight) {
            r.push([]);
        }
        r[r.length - 1].push(o);
        return r;
    }, []);

console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

Nenad Vracar
Nenad Vracar

Reputation: 122027

You can do this with reduce() method you just need to keep track of current index for final array.

const data =[
  {score: 5, question: 0, weight: 2},
  {score: 4, question: 1, weight: 2},
  {score: 3, question: 0, weight: 4},
  {score: 4, question: 1, weight: 4},
  {score: 2, question: 2, weight: 4},
  {score: 8, question: 0, weight: 2}
]

const result = data.reduce(function(r, e, i) {
  if(i == 0) r = {values: [], counter: 0}
  if(e.question == 0 && i != 0) r.counter++
  if(!r.values[r.counter]) r.values[r.counter] = [e]
  else r.values[r.counter].push(e)
  return r;
}, {}).values

console.log(result)

Upvotes: 2

Related Questions