Reputation: 1816
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;
}
Upvotes: 0
Views: 149
Reputation: 50759
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);
Upvotes: 2