I have below two array:
var val = [['aa', 'ab', 'ac'], ['bb', 'bc', 'bd']];
var key = ['item1', 'item2', 'item3'];
By using any javascript logic I want to get a new array in below format.
[
{item1: 'aa', item2: 'ab', item3: 'ac'},
{item1: 'bb', item2: 'bc', item3: 'bd'}
]
I tried using .forEach and .map() to achieve this, but somehow I couldn't able to do it.
Here is the sample code I tried.https://plnkr.co/edit/oKyjNsBu3wrRin7TaCIb?p=preview
var val = [['aa', 'ab', 'ac'], ['bb', 'bc', 'bd']];
var key = ['item1', 'item2', 'item3'];
var newArr = val.map((elm,i)=>{
return {[key[i]]: elm[i]}
})
console.log('newArr', newArr);
I need the output as below.
[
{item1: 'aa', item2: 'ab', item3: 'ac'},
{item1: 'bb', item2: 'bc', item3: 'bd'}
]
You can use .map() and .reduce() methods to get the desired output:
const vals = [['aa','ab','ac'],['bb','bc','bd']];
const keys = ['item1','item2','item3'];
const result = vals.map((val) => keys.reduce((r, c, i) => (r[c] = val[i], r), {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Map the val array (change its name to allVals for better clarity) to objects using Object.fromEntries:
var allVals = [['aa','ab','ac'],['bb','bc','bd']];
var keys = ['item1','item2','item3'];
const output = allVals.map(vals => Object.fromEntries(
vals.map((val, i) => [keys[i], val])
));
console.log(output);
Using Object.fromEntries():
const values = [['aa','ab','ac'],['bb','bc','bd']];
const keys = ['item1','item2','item3'];
const result = values.map(v => Object.fromEntries(keys.map((k, i) => [k, v[i]])));
console.log(result);
Related
I have this JavaScript array of arrays
arr1= [
['a', 'b'],
['1', '2']
]
And I need to form this JSON object
[
{
"label":"a",
"value":"1"
},
{
"label":"b",
"value":"2"
},
]
How do I do it?
Using Array#map:
const arr = [ ['a', 'b'], ['1', '2'] ];
const [labels, values] = arr;
const res = labels.map((label, index) => ({ label, value: values[index] }));
console.log(res);
Look at this ...
const entries = new Map([
['foo', 'bar'],
['baz', 42]
]);
const obj = Object.fromEntries(entries);
console.log(obj);
// expected output: Object { foo: "bar", baz: 42 }
Did you mean something like this?
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries
You could take an array with the keys of the wanted objects and reduce and map the items.
const
data = [['a', 'b'], ['1', '2']],
keys = ['label', 'id'],
result = data.reduce((r, a, i) => a.map((v, j) => ({ ...r[j], [keys[i]]: v })), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I have an object like this -
const obj = {
'a': 1,
'b': 2,
'c': 3,
'd': 4,
'e': 5
}
and an array containing keys belonging to the object,
const arr = ['a', 'b', 'd']
I want to return an object similar to obj but it shouldn't contain the keys present in arr,
i.e., I want an object which will be
const result = {
'c': 3,
'e': 5
}
How can I achieve this via Javascript?
With the new Object.fromEntries, it's easy:
const result = Object.fromEntries(Object.entries(obj).filter(([k, _]) => !arr.includes(k)))
Without it, it takes a bit more effort:
const result = Object.entries(obj).reduce((tot, [k, v]) => {
if (!arr.includes(k)) {
tot[k] = v;
}
return tot;
}, {})
You can copy the object and delete the listed properties:
const obj = {a:1,b:2,c:3,d:4,e:5};
const arr = ['a', 'b', 'd'];
const res = {...obj};
for (let k of arr) delete res[k];
console.log(res);
Note that this has a time complexity that is almost linear in terms of the number of properties involved, O(m+nlogn) (if delete is O(logn)), while Aplet's answer would have a quadratic time complexity: O(mn).
Using Object.entries, you can generate [key, value] pair from object as array.
And based on that, using Array.reduce, you can get the result you want.
const obj = {
'a': 1,
'b': 2,
'c': 3,
'd': 4,
'e': 5
};
const arr = ['a', 'b', 'd'];
const result = Object.entries(obj).reduce((acc, cur) => {
if (!arr.includes(cur[0])) {
acc[cur[0]] = cur[1];
}
return acc;
}, {});
console.log(result);
Array#reduce solution:
const obj = {'a': 1,'b': 2,'c': 3,'d': 4,'e': 5};
const arr = ['a', 'b', 'd'];
const o = Object.keys(obj)
.reduce((s, a) => (arr.indexOf(a) > -1 ? s : s[a] = obj[a], s), {});
console.log(o);
You could destructure the object and get the rest of it without unwanted keys.
const
object = { a: 1, b: 2, c: 3, d: 4, e: 5 },
without = ['a', 'b', 'd'],
result = without.reduce((r, k) => ({ [k]: _, ...r } = r, r), object);
console.log(result);
Traverse the object using JavaScript for..in loop. Check property using array indexOf method. If property name is not present in the array then put the property with value in ret variable.
const obj = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5,
};
const arr = ["a", "b", "d"];
ret = {};
for (let x in obj) if (arr.indexOf(x) === -1) ret[x] = obj[x];
console.log(ret);
You can do this using Object#entries then filter out those entries which are not in the arr and using Object#fromEntries reconstruct the object:
const obj = {'a': 1,'b': 2,'c': 3,'d': 4,'e': 5}, arr = ['a', 'b', 'd'];
const filterObj = (obj, arr) => {
const dataSet = new Set(arr);
return Object.fromEntries(Object.entries(obj)
.filter(([k, v]) => !dataSet.has(k)))
};
console.log(filterObj(obj, arr));
Another way to filter the object with the supplied keys but without using Object#fromEntries is by using Object#assign.
We would just filter the entries which are not in the given array, then map them to objects and pass those as parameters to the Object#assign:
const obj = {'a': 1,'b': 2,'c': 3,'d': 4,'e': 5}, arr = ['a', 'b', 'd'];
const filterObj = (obj, arr) => {
const keySet = new Set(arr);
const filteredEntries = Object.entries(obj).filter(([k, v]) => !keySet.has(k));
return Object.assign({}, ...filteredEntries.map(([k, v]) => ({[k]: v})));
}
console.log(filterObj(obj, arr));
From an array of keys and an array of arrays, like this:
const keys = ['foo', 'bar'];
const vals = [
['a', 'A'],
['b', 'B']
];
How to get an array of objects like below ?
[
{'foo' : 'a', 'bar' : 'A'},
{'foo' : 'b', 'bar' : 'B'}
]
Maybe using lodash ?
You can use loash's _.zipObject() to create an object from an array of keys and values for each value array inside your 2d array using the _.map() method:
const keys = ['foo', 'bar']
const vals = [
['a', 'A'],
['b', 'B']
];
const res = _.map(vals, arr => _.zipObject(keys, arr));
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
If you prefer vanilla JS, then you could use Object.fromEntries() on a zipped array (created using .map()):
const keys = ['foo', 'bar']
const vals = [
['a', 'A'],
['b', 'B']
];
const res = vals.map(
arr => Object.fromEntries(arr.map((v, i) => [keys[i], v]))
);
console.log(res);
To be more generic, you can use Array.reduce() with index variable
const keys = ['foo', 'bar']
const values = [
['a', 'A'],
['b', 'B']
]
const mapped = values.map(val => val.reduce((acc, cur, i) => ({...acc, [keys[i]]: cur}),{}))
console.log(mapped)
With lodash/fp you can generate a function using _.flow(), that curries _.zipObject() with the keys, and the _.map() with the curried _.zipObject(), and then you can call it with vals to get the array of objects:
const fn = _.flow(_.zipObject, _.map);
const keys = ['foo', 'bar']
const vals = [
['a', 'A'],
['b', 'B']
];
const result = fn(keys)(vals);
console.log(result);
<script src='https://cdn.jsdelivr.net/g/lodash#4(lodash.min.js+lodash.fp.min.js)'></script>
You can do it simply using reduce.
let keys = ['foo', 'bar'];
let values = [
['a', 'A'],
['b', 'B']
];
const res = values.reduce((a, [first, second]) => {
return [...a, {[keys[0]]: first, [keys[1]]: second}];
}, []);
console.log(res);
.as-console-wrapper{min-height: 100%!important; top:0}
let dataKeys = ['foo', 'bar'];
let dataValues = [
['a', 'A'],
['b', 'B']
];
let transformed = dataValues.reduce((result,item)=>{
result.push(
dataKeys.reduce((r,dk,index)=>{
let o = {};
o[dk]= item[index];
return {...r, ...o}
},{})
)
return result
},[]);
console.log(JSON.stringify(transformed,null,2));
I have a array has a value of ['a', 'b', 'c', 'd', 'e'] now I want it to become a object that have it's value so I do some array mapping
const arrs = ['a', 'b', 'c', 'd', 'e']
let arrObj = arrs.map(arr => {
return {value: arr}
})
Now the value of arrObj is
[{value: 'a'}, {value: 'b'}, {value: 'c'}, {value: 'd'}, {value: 'e'}]
But what I want to do is to insert a object in the middle of each object that is inside the array that has a value of {operator: '+'} so the value of arrObj will be
[{value: 'a'}, {operator: '+'}, {value: 'b'}, {operator: '+'}, {value: 'c'}, {operator: '+'}, {value: 'd'}, {operator: '+'}, {value: 'e'}]
now, using javascript, how can I achive that function given that I'm setting a value of arrObj in array.map() ?
You could create a new array with a double length minus one and add the required values, depending on the index.
var values = ['a', 'b', 'c', 'd', 'e'],
result = Array.from(
{ length: values.length * 2 - 1 },
(_, i) => i % 2
? { operator: '+' }
: { value: values[i >> 1] }
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
One option is to map each element (but the last) to an array with that element and another with the +, then flatten:
const arrs = ['a', 'b', 'c', 'd', 'e'];
const transformed = arrs
.map((char, i) => (
i === arrs.length - 1
? [{ value: char }]
: [{ value: char }, { value: '+' }]
))
.flat();
console.log(transformed);
If + won't appear in the input array, then you can join by + initially, then split:
const arrs = ['a', 'b', 'c', 'd', 'e'];
const output = arrs
.join('+')
.split('')
.map(value => ({ value }));
console.log(output);
Use flatMap and return a pair from the callback. Finally, remove the extra element.
const arrs = ['a', 'b', 'c', 'd', 'e']
let arrObj = arrs.flatMap(x => [
{operator: '+'}, {value: x}
]).slice(1)
console.log(arrObj)
If your platform doesn't have flatMap yet, it's trivial to polyfill:
Array.prototype.flatMap = function(fn) {
return this.concat.apply([], this.map(fn))
}
Generic function:
let interleave = (ary, val) => ary.flatMap(x => [val, x]).slice(1);
//
let arrObj = interleave(
arrs.map(x => ( {value: x})),
{operator: '+'}
)
What about using reduce?
let arrObj = arrs.reduce((acc, curr, index) => {
if (index === arrs.length - 1) acc = [...acc, {value: curr}];
else acc = [...acc, {value: curr}, {operator: '+'}];
return acc;
}, [])
Concat your required object and deep flatten it like below:
var arrs = ['a', 'b', 'c', 'd','e'];
const arrObj = arrs.map((arr,i) => {
let item = [{value: arr}];
if(i < arrs.length-1)
item.push({operator: '+'});
return item;
});
console.log(flattenDeep(arrObj));
function flattenDeep(arr1) {
return arr1.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), []);
}
For more details take a look here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat
I have 4 arrays of the following format
arr1 = ['Hello', 'World', 'Hi']
arr2 = ['1', '2', '3']
arr3 = ['foo', 'bar', 'foobar']
arr4 = ['10', '20', '30']
I am trying to add each value at index[i] to a new object, the object looks like this
obj = {
title: '',
score: '',
description: '',
value: '',
}
For each indexed value in the array I would like to push it to a new instance of the obj object so I can end up with this
objects = [
{
title: 'Hello',
score: '1',
description: 'foo',
value: '10',
},
{
title: 'World',
score: '2',
description: 'bar',
value: '20',
},
{
title: 'Hi',
score: '3',
description: 'foobar',
value: '30',
}
]
So far I have been trying something like
objects = []
arr1.forEach((key, i) => objects[key] = arr2[i])
But that is assigning them as arr1val : arr2val
I will ultimately be setting this to state in my react app and passing it to another component as props to render on the page. The data is coming in from 3 different APIs, I am doing this to try and standardise the data received from each API so my component can use the data to render an articles list and user can switch between feeds.
Map by the index of element across all arrays, also use map not forEach:
const objects = arr1.map((element, index) => (
{title: element, score: arr2[index], description: arr3[index], value: arr4[index]}
))
Live demo is below:
const arr1 = ['Hello', 'World', 'Hi']
const arr2 = ['1', '2', '3']
const arr3 = ['foo', 'bar', 'foobar']
const arr4 = ['10', '20', '30']
const objects = arr1.map((element, index) => (
{title: element, score: arr2[index], description: arr3[index], value: arr4[index]}
))
console.log(objects)
This code also works:
var arr = [];
for(var i=0; i<arr1.length; i++) {
arr[i] = {};
arr[i].title = arr1[i];
arr[i].score = arr2[i];
arr[i].description = arr3[i];
arr[i].value = arr4[i];
}
I suggest to use an array of arrays and another array for the keys. This allows an arbitrary count of arrays and keys to use for transforming the data into an array of objects with hte wanted properties.
var array1 = ['Hello', 'World', 'Hi'],
array2 = ['1', '2', '3'],
array3 = ['foo', 'bar', 'foobar'],
array4 = ['10', '20', '30'],
keys = ['title', 'score', 'description', 'value'],
result = [array1, array2, array3, array4].reduce(function (r, a, i) {
a.forEach(function (v, j) {
r[j] = r[j] || {};
r[j][keys[i]] = v;
});
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
If you don't want to type the property names twice,
you could do like this:
const descriptor = {
title: arr1,
score: arr2,
description: arr3,
value: arr4
};
const objects = arr1.map((tmp, i) => {
var o = {};
Object.keys(descriptor).forEach(name => o[name] = descriptor[name][i]);
return o;
});
A reducer method would be in place I suppose
const arr1 = ['Hello', 'World', 'Hi', 'Hello2', 'World2', 'Hi2'];
const arr2 = ['1', '2', '3', '11', '22', '33'];
const arr3 = ['foo', 'bar', 'foobar', 'sea', 'shell', 'sea weed'];
const arr4 = ['10', '20', '30', '100', '200', '300'];
const arrays2Objects = arr1.reduce( (obj, next, i) =>
obj.concat({title: next, score: arr2[i], description: arr3[i], value: arr4[i]}),
[]
);
console.log(arrays2Objects);