0

I really apologize for the question title, I don't know how to phrase the question. I have an array of objects that have inter relationships with each other and I need to group them by those relationships with the names associated with those relationships. Here is the array of objects.

let someResponse = [
  {code: "00000000001524", relationship: "ally", name: "Batman"},
  {code: "00000000001524", relationship: "other", name: "Superman"},
  {code: "00000000001111", relationship: "adversary", name: "Scarecrow"},
  {code: "00000000008888", relationship: "neutral", name: "Strange"},
  {code: "00000000008888", relationship: "ally", name: "Robin"},
  {code: "00000000008888", relationship: "neutral", name: "Vale"}
];

Notice how you have similar codes and with those similar codes you will notice relationships and with those relationship, names. I need the names grouped based on the realtionship while ensuring it is in the same code. The result will look like this...

result = [
    {code: "00000000001524", relationship: "ally", names: ["Batman"]},
    {code: "00000000001524", relationship: "other", names: ["Superman"]},
    {code: "00000000001111", relationship: "adversary", names: ["Scarecrow"]},
    {code: "00000000008888", relationship: "neutral", names: ["Strange", "Vale"]},
    {code: "00000000008888", relationship: "ally", names: ["Robin"]}
]

Of course I could do a compare function and sort by code and then by relationship, but that will end changing my array of objects and I need the same code order otherwise it will mess things up later in my code, so I don't want to do that. I'm really stumped on how to do this.

I'm guessing you would start off by doing something like this...?

function rearrangeObject(response){
  let newArrangedArr = [];
  for(let i = 0; i<response.length;){
    let count = i;
    while(response[i].code === response[count].code){
      //Something goes here
      count++;
      if(count === response.length){break;}
    } 
    i = count;
  }
  return newArrangedArr;
}

1 Answer 1

2

You can use .reduce() with an object as an accumulator. For each key in the object, you can use a combination of the code and relationship. Then, for each object in your array, if you encounter a key in the accumulator object which matches the code+relationship of your current object you can add the name to value array held by the accumulator:

const someResponse = [
  {code: "00000000001524", relationship: "ally", name: "Batman"},
  {code: "00000000001524", relationship: "other", name: "Superman"},
  {code: "00000000001111", relationship: "adversary", name: "Scarecrow"},
  {code: "00000000008888", relationship: "neutral", name: "Strange"},
  {code: "00000000008888", relationship: "ally", name: "Robin"},
  {code: "00000000008888", relationship: "neutral", name: "Vale"}
];

const res = Object.values(someResponse.reduce((acc, {code, relationship, name}) => {
  const key = `${code}-${relationship}`;
  acc[key] = acc[key] || {code, relationship, names: []}
  acc[key].names.push(name);
  return acc;
}, {}));

console.log(res);

If you don't feel comfortable using .reduce() and destructuring, you can achieve the same result using a for loop with an object, which, in essence, does the same thing:

const someResponse = [
  {code: "00000000001524", relationship: "ally", name: "Batman"},
  {code: "00000000001524", relationship: "other", name: "Superman"},
  {code: "00000000001111", relationship: "adversary", name: "Scarecrow"},
  {code: "00000000008888", relationship: "neutral", name: "Strange"},
  {code: "00000000008888", relationship: "ally", name: "Robin"},
  {code: "00000000008888", relationship: "neutral", name: "Vale"}
];

const acc = {};
for(const obj of someResponse) {
  const key = obj.code + '-' +obj.relationship;
  acc[key] = acc[key] || {code: obj.code, relationship: obj.relationship, names: []} // use object sotred at key or default it to a new object with a `names` array
  acc[key].names.push(obj.name); // push the current name into the object;
}
const res = Object.values(acc);
console.log(res);

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

2 Comments

Thanks Nick, it's perfect and it maintains the code property integrity which is vital for what I'm doing. I'm definitely going to pour over this to greater my understanding.
@Travis no worries, I added an approach using a for loop which does the same thing .reduce() does, the for loop approach is probably more intuitive to understand if you haven't had much experience with .reduce(). Both snippets of code do the same thing though

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.