Create object with list of keys - javascript

What is the concisest way to create an object from a list of keys, all set to the same value. For example,
const keys = [1, 2, 3, 4]
const value = 0
What is the tersest way to attain the object
{
“1”: 0,
“2”: 0,
“3”: 0,
“4”: 0
}

You can use Object.fromEntries
const keys = [1, 2, 3, 4]
const value = 0
const result = Object.fromEntries(keys.map(k => [k, value]))
console.log(result)

Should probably be something among:
const keys = [1, 2, 3 ,4];
const value = 0;
console.log(
keys.reduce((acc, key) => (acc[key] = value, acc), {})
);

The simplest way I can think of would be to use .reduce();
const keys = [1, 2, 3, 4]
const value = 0
const obj = keys.reduce((carry, item) => {
carry[item] = value;
return carry;
}, {});
console.log(obj);

Related

How to filter an array and return new array of objects with indexed values?

Given the array const vals = [1, 2, 3, 4, 5, 6, 7, 8, 9];
How can I filter and return a new array of indexed key/value pair objects for example:
const vals = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// My fail attempt using filter()
let obj = vals.filter((n, i) => {
return new Object({ i: n % 2 });
});
return obj;
// expected result [{1:2}, {3:4}, {5:6}, {7:8}]
I need to keep the index values as I will filter 2 different arrays with different criteria and associated them later.
Update
Second attempt using map() as suggested in the comments
let obj = vals.map((n, i) => {
if (n % 2) {
return { [i]: n };
}
});
Gives me the following:
[{0:1}, undefined, {2:3}, undefined, {4:5}, undefined, {6:7}, undefined, {8:9}]
To get a list of { key: value } objects where key is the index, and the values are only even without the odd values, you can do this:
const vals = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const result = vals.map((v, i) => [i, v])
.filter(([_, v]) => v % 2 == 0)
.map(([i, v]) => ({ [i]: v }));
console.log(result);
With the first map, you make a list of [[0, 1], ...] pairs to save the index for later.
Then you filter your index-value pairs so only even values remain.
Then you pack those pairs into an object in another map.
This can be done more efficiently with a single iteration using reduce:
const vals = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const result = vals.reduce((a, v, i) => {
if (v % 2 == 0) {
a.push({ [i]: v });
}
return a;
}, []);
console.log(result);
Youn can try simple for loop or the reduce function
let arr = [];
for(let i = 0; i<vals.length-1;i += 2)
{
let obj={};
obj[vals[i]]=vals[i+1];
arr.push(obj);
};

Convert an object to a query string

i have the following object
let filters = {
first_ids: [1,2,3],
second_ids: [2,4,9]
}
Now, i want to loop over them and then return something like the following.
filters[first_ids][]=1&filters[first_ids][]=2&filters[first_ids][]=3&filters[second_ids][]=2&filters[second_ids][]=4&filters[second_ids][]=9&
What i tried is following, but i know this is not a elegant way.
let filters = {
first_ids: [1,2,3],
second_ids: [2,4,9]
}
let finalFilters = []
let firstFilters = filters.first_ids.map((e) => `filters[first_ids][]=${e}&`)
let secondFilters = filters.second_ids.map((e) => `filters[second_ids][]=${e}&`)
finalFilters.push(firstFilters)
finalFilters.push(secondFilters)
finalFilters.toString().replace(/,/g, "")
Also the filters object can have more keys.
Something like this might work:
let filters = {
first_ids: [1, 2, 3],
second_ids: [2, 4, 9],
};
const output = Object.entries(filters).flatMap(([name, ids]) => {
return ids.map(id => {
return `filters[${encodeURIComponent(name)}]=${encodeURIComponent(id)}`;
});
}).join('&');
console.log(output)
The main idea is to look though each key, value pair in the object fitlers, then loop though all the ids, and construct the query string fragment, and finally join it on &.
Take a look at Object.entries, Array.prototype.flatMap and encodeURIComponent
You could take a nested approach for generating the string.
const
filters = { first_ids: [1, 2, 3], second_ids: [2, 4, 9] },
result = Object
.entries(filters)
.flatMap(([k, a]) => a.map(v => `filters[${k}][]=${v}`))
.join('&');
console.log(result);
reduce into an array first and then use join.
let filters = {
first_ids: [1, 2, 3],
second_ids: [2, 4, 9],
};
const res = Object.entries(filters)
.reduce((r, [k, v]) => (v.forEach((n) => r.push(`filters[${k}][]=${n}`)), r), [])
.join("&");
console.log(res)
Here's some generic solution:
function toPhpQueryString(o, key) {
if (o === null || o === undefined)
return '';
if (typeof o !== 'object')
return key + '=' + encodeURIComponent(o);
if (Array.isArray(o))
return o.map(v =>
toPhpQueryString(v, key + '[]')).join('&');
return Object.entries(o).map(p =>
toPhpQueryString(p[1], key + '[' + p[0] + ']')).join('&');
}
//
let filters = {
first_ids: [1, 2, 3],
second_ids: [2, 4, 9],
deep: {
object: {
abc: [33, 44],
xyz: 'hey',
}
}
}
qs = toPhpQueryString(filters, 'filters');
console.log(qs)

Javascript: calculate the total sum of all the object values in an array

I have an array of objects as the following;
[{"A":"34"},{"B":"13"},{"C":"35"},{"D":"74"}]
If the key is A, it's value has to be multiply by 30,B by 10,C by 5,D by 2. I would like to calculate the total sum after the multiplication;
34*30 + 13*10 + 35*5 + 74*2
Is there a way to achieve this other than an if/else statement? Thanks!
Reduce the array, and get the key / value pair by destructuring the array produce by calling Object.entries() on the each item. Get the value of the key, multiply by current value, and add to the accumulator.
const multi = { A: 30, B: 10, C: 5, D: 2 }
const fn = arr =>
arr.reduce((acc, item) => {
const [[k, v]] = Object.entries(item)
return acc + multi[k] * v
}, 0)
const arr = [{"A":"34"},{"B":"13"},{"C":"35"},{"D":"74"}]
const result = fn(arr)
console.log(result)
let input = [{"A": "34"}, {"B": "13"}, {"C": "35"}, {"D": "74"}];
let multiply = {A: 30, B: 10, C: 5, D: 2};
let result = input.reduce((sum, v) =>
sum + Object.values(v)[0] * multiply[Object.keys(v)[0]], 0);
console.log(result);
You can easily achieve this using Object.entries
const arr = [{ A: "34" }, { B: "13" }, { C: "35" }, { D: "74" }];
const multiplier = {
A: 30,
B: 10,
C: 5,
D: 2,
};
const result = arr.reduce((acc, curr) => {
const [[key, value]] = Object.entries(curr);
return acc + multiplier[key] * parseInt(value);
}, 0);
console.log(result);
You can create an dictionary to get the number with which the value should be multiplied as shown :
{"A":30, "B":13, "C":35, "D":74}
Now you can loop through your array of objects, and fetch the value from the dictionary using the key of the object:
const myArray = [{"A":"34"},{"B":"13"},{"C":"35"},{"D":"74"}]
const Nums = {"A":30, "B":10, "C":5, "D":2};
let Result = 0;
myArray.forEach((item)=>{
const key = Object.keys(item)[0];
var temp= parseInt(item[key]);
Result += temp*Nums[key];
})
console.log(Result);
Not sure how you map your values so that "A" === 30. But assuming you have a map:
const map = {
"A": 30,
"B": 10,
"C": 5,
"D": 2
}
const array = [{"A":"34"},{"B":"13"},{"C":"35"},{"D":"74"}];
Then in one line:
const outcome = array.map(element => map[Object.keys(element)[0]] * Object.values(element)[0]).reduce((acc, init) => acc + init, 0)

create a new object w/ unique IDs and specific indeces

I want a clean way to create a new object from the given data:
const groups = [1, 2, null, 1, 1, null]
here is my target:
// key = unique id, value = index of unique id in groups
const target = {
null: [2, 5],
1: [0, 3, 4],
2: [1]
}
I try to reach:
the object keys of target are the unique entries of the groups array
to get the index of each value of the unique id and save them in an own array
my current approach:
const groupIDs = [1, 2, null, 1, 1, null]
const group = {}
const uniqueIDs = [...new Set(groupIDs)]
uniqueIDs.forEach(uid => {
const arr = groupIDs.map((id, idx) => uid === id ? idx : null)
const filtered = arr.filter(idx => idx !== null)
Object.assign(group, { [uid]: filtered })
})
You could reduce the array directly by using an object as accumulator and take the values as key and the indices as value for the grouped arrays.
This approach features an logical nullish assignment ??= where the right side is assigned to the left, if the LHS is undefined or null.
const
groups = [1, 2, null, 1, 1, null],
target = groups.reduce((r, value, index) => {
r[value] ??= [];
r[value].push(index);
return r;
}, {});
console.log(target);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Is there any direct method which returns the sum of lengths of arrays in the array of objects?

I have an array of objects and I want to find the sum of length of arrays of a certain property(key).
I have this array of objects like
var myArray =
[{
"a" : 1,
"b" : another Array
},
{
"c" : 2,
"b" : another Array
}
.....
]
Is there any way to simplify this below process?
var lengthOfEachObject = myArray.map(function(Obj){
if(Obj.b){
return Obj.b.length;
}
else{
return 0;
}
});
lengthofEachObject.reduce(function(x,y){
return x+y;
})
Answers can also include use of external libraries.
You can use .reduce without .map, this way you can get the total sum by only iterating once over your array. Furthermore, you can use destructing assignment instead of your if statements to set a default value for your b.length if it doesn't exist.
See working example below:
const arr = [{a: 1, b: [1, 2, 3, 4, 5] }, {c: 2, b: [1, 2, 3]}, {e: 3}],
total = arr.reduce((acc, {b={length:0}}) => acc + b.length, 0);
console.log(total);
You can use lodash's _.sumBy():
var myArray = [{"a":1,"b":[1,2,3]},{"c":2,"b":[4,5,6,7,8]},{"c":2}]
var result = _.sumBy(myArray, 'b.length')
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
You could pull out the length with a closure over the wanted key and map this value.
const
length = k => ({ [k]: { length = 0 } = {} }) => length,
add = (a, b) => a + b,
array = [{ a: 1, b: [1, 2, 3, 4] }, { c: 2, b: [1, 2, 3] }];
console.log(array.map(length('b')).reduce(add));
console.log(array.map(length('a')).reduce(add));

Categories