I'm trying to make an array with unique keys and assigned incremented values, in order to end up with a weighted list.
In PHP, I do it like this...
$crit1 = ['a','b','c'];
$crit2 = ['c','d','e'];
$weight = [];
foreach ( $crit1 as $item ) {$weight[$item] += 1;}
foreach ( $crit2 as $item ) {$weight[$item] += 2;}
// print_r($weight); => array([a] => 1 [b] => 1 [c] => 3 [d] => 2 [e] => 2)
...with 'c' ending up with the most points: 1 for showing up in the first foreach and another 2 for being featured in the second.
Trying to translate this to JS...
const crit1 = ['a','b','c'];
const crit2 = ['c','d','e'];
let weight = [];
crit1.forEach(function (item) { weight.push({ [item]: +1 }) });
crit2.forEach(function (item) { weight.push({ [item]: +2 }) });
// console.log(weight) => [{ a: 1}, { b: 1}, { c: 1}, { c: 2}, { d: 2}, { e: 2}]
...no longer works – the values for 'c' are assigned separately so the array comes up with 6 items instead of just 5.
What am I doing wrong?
Instead of an array, use an object so the keys value can be bumped
Since we're using an object, we can't use push
, but we'll need to address the key
weight[item] = (weight[item] || 0) + 1)
Increments the current item
key in the weight
object by 1
, if it's not defined yet, we set it to 0
.
const crit1 = ['a','b','c'];
const crit2 = ['c','d','e'];
let weight = {};
crit1.forEach((item) => weight[item] = (weight[item] || 0) + 1);
crit2.forEach((item) => weight[item] = (weight[item] || 0) + 2);
let arr = Object.keys(weight).reduce((prev, cur) => [ ...prev, { [cur]: weight[cur] } ], []);
console.log(weight);
console.log(arr);
{
"a": 1,
"b": 1,
"c": 3,
"d": 2,
"e": 2
}
If you really want an array containing objects with just a single key, as shown in your comment, we can use reduce()
to do the conversion:
let arr = Object.keys(weight).reduce((prev, cur) => [ ...prev, { [cur]: weight[cur] } ], []);
Will produce:
[
{
"a": 1
},
{
"b": 1
},
{
"c": 3
},
{
"d": 2
},
{
"e": 2
}
]