Reputation: 663
If have an array like this:
let array = [
{hash: "11223344", value: "abc"},
{hash: "11223344", value: "def"},
{hash: "22113344", value: "jkl"},
{hash: "22113344", value: "zyw"},
{hash: "33221144", value: "omn"},
{hash: "33221144", value: "xyz"}
];
and I wanted to loop through that array and create a new array whereby each each hash
is only listed once and each value
that was listed with a given is added to an array at the key value in the object of the single hash
, like this:
let newarray = [
{hash: "11223344", value: ["abc", "def"]},
{hash: "22113344", value: ["jkl", "zyw"]},
{hash: "33221144", value: ["omn", "xyz"]},
];
How would I get there?
Im thinking its something like
array.map((item, i, self) => {
let newArray =[];
if(item.hash === newArray.hash){
newArray.value.concat(item.value)
} else {
newArray.concat({hash: item.hash, value: [item.value]})
}
but how do I instantiate that array at first in the value
key?
Is my thinking right on the use of the Array.prototype.map()
?
EDIT: I was asked to explain how this question is different than: How to group an array of objects by key
In contrast to the link, there is no need to group the results and I dont want to use a library like LoDash. The clarity provided about creating the array in the value
key also has some worth.
I think the answers here also point out the need to use the index and provides several valid tools, some of which arent provided in the answers in the other questions. Tools such as reduce()
and Set
Upvotes: 0
Views: 201
Reputation: 36299
Use a set to get an unique list of hashes, then match each item on the unique set using filter and map.
let array = [
{hash: "11223344", value: "abc"},
{hash: "11223344", value: "def"},
{hash: "22113344", value: "jkl"},
{hash: "22113344", value: "zyw"},
{hash: "33221144", value: "omn"},
{hash: "33221144", value: "xyz"}
];
let a = [...new Set(array.map(i => i.hash))]
.map(hash => {
return { hash, values: array.filter(v => v.hash == hash).map(v => v.value) }
})
console.log(a)
Upvotes: 2
Reputation: 40
You could simply use a for loop to achieve this:
array = [
{hash: "11223344", value: "abc"},
{hash: "11223344", value: "def"},
{hash: "22113344", value: "jkl"},
{hash: "22113344", value: "zyw"},
{hash: "33221144", value: "omn"},
{hash: "33221144", value: "xyz"}
];
newArray = []
for (var i = array.length - 1; i >= 0; i--) {
if (newArray[array[i].hash] == null) {
newArray[array[i].hash] = [array[i].value];
} else {
newArray[array[i].hash].push(array[i].value)
}
}
console.log(newArray);
Upvotes: 0
Reputation: 2646
Take a look at the following code where we maintain the index of hash encountered before and insert the value to existing object else insert a new object in the results array.
let data = [{
hash: "11223344",
value: "abc"
},
{
hash: "11223344",
value: "def"
},
{
hash: "22113344",
value: "jkl"
},
{
hash: "22113344",
value: "zyw"
},
{
hash: "33221144",
value: "omn"
},
{
hash: "33221144",
value: "xyz"
}
];
function aggregateValues(arr) {
let hashMap = {};
let result = [];
arr.forEach((o) => {
if (hashMap[o.hash] !== undefined) {
result[hashMap[o.hash]].value.push(o.value);
} else {
hashMap[o.hash] = result.length;
result.push({
hash: o.hash,
value: [o.value]
});
}
})
return result;
}
console.log(aggregateValues(data))
Upvotes: 0
Reputation: 386560
You could take a Map
and render the collected items with Array.from
.
var array = [{ hash: "11223344", value: "abc" }, { hash: "11223344", value: "def" }, { hash: "22113344", value: "jkl" }, { hash: "22113344", value: "zyw" }, { hash: "33221144", value: "omn" }, { hash: "33221144", value: "xyz" }],
grouped = Array.from(
array.reduce((map, { hash, value }) =>
map.set(hash, (map.get(hash) || []).concat(value)), new Map),
([hash, value]) => ({ hash, value })
);
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 0
Reputation: 5031
You can use reduce
like below
let array = [
{hash: "11223344", value: "abc"},
{hash: "11223344", value: "def"},
{hash: "22113344", value: "jkl"},
{hash: "22113344", value: "zyw"},
{hash: "33221144", value: "omn"},
{hash: "33221144", value: "xyz"}
];
let result = array.reduce((acc, ele) => {
let index = acc.findIndex(e => e.hash === ele.hash);
if (index == -1) {
acc.push({
hash: ele.hash,
value: [ele.value]
})
} else {
acc[index].value.push(ele.value);
}
return acc;
}, []);
console.log(result);
Upvotes: 0
Reputation: 50291
You can use reduce
function to return a new array.Inside reduce callback use findIndex
to find the index of the object where the hash matches. If this hash match then update the value
array, else create a new object, set it's key and value and push it
let array = [{
hash: "11223344",
value: "abc"
},
{
hash: "11223344",
value: "def"
},
{
hash: "22113344",
value: "jkl"
},
{
hash: "22113344",
value: "zyw"
},
{
hash: "33221144",
value: "omn"
},
{
hash: "33221144",
value: "xyz"
}
];
let reducedArray = array.reduce(function(acc, curr) {
let getHashIndex = acc.findIndex(function(item) {
return item.hash === curr.hash;
})
if (getHashIndex === -1) {
let obj = {};
obj.hash = curr.hash;
obj.value = [];
obj.value.push(curr.value);
acc.push(obj)
} else {
acc[getHashIndex].value.push(curr.value)
}
return acc;
}, [])
console.log(reducedArray)
Upvotes: 1