Javascript merge the values of 4 arrays into one object - javascript

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);

Related

Filtering an array with an array of values

I have 2 arrays and i'd like to filter one array with the other. E.g. if array1 includes any of the values in array2, they should be returned.
The two arrays are:
const array1 = [a, b, c, d]
The other array, which should be filtered where 'id' is equal to any of the values in array1 is:
const array2 = [
{
id: b
title: title1
},
{
id: d
title: title2
},
{
id: f
title: title3
}
]
The easiest way is to use two for-loops. Possible not the fastest approach.
res = [];
for (var i = 0;i<array1.length;i++) {
for (var j = 0;j<array2.length;j++) {
if (array1[i] == array2[j].id) {
res.push(array2[j]);
break;
}
}
}
You could use Array.prototype.filter() and Array.prototype.indexOf():
const array1 = ['a', 'b', 'c', 'd'];
const array2 = [{
id: 'b',
title: 'title1'
}, {
id: 'd',
title: 'title2'
}, {
id: 'f',
title: 'title3'
}];
const result = array2.filter(function(x){
return array1.indexOf(x.id) !== -1;
});
Adding this missing '', You can use filter and includes methods of Array.
const array1 = ['a', 'b', 'c', 'd'];
const array2 = [
{
id: 'b',
title: 'title1'
},
{
id: 'd',
title: 'title2'
},
{
id: 'f',
title: 'title3'
}
]
const result = array2.filter(({id}) => array1.includes(id));
console.log(result);

Nested array manipulation

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);

Turning and array into an object

I have an array of elements containing iPhone models and 4 values that come after it, like this:
const arr = ['ip6s+', '35', '15', '10', '10', 'ip7', '40', '20', '15', '15']
I want to turn this into an object that looks like this:
const Obj = {
'ip6s+': ['35', '15', '10', '10'],
'ip7+' : ['90', '60', '35', '30']
}
Where the first object is the phone model and every fourth is its values. How to do that?
You can use slice:
const arr = ['ip6s+', '35', '15', '10', '10','ip7', '40', '20', '15','15'];
const obj = {};
const n = 4; // the number of values after the model name
for (var i = 0; i < arr.length; i += n + 1) {
obj[arr[i]] = arr.slice(i + 1, i + n + 1);
}
console.log(obj);
You could also use reduce()
const arr = ['ip6s+', '35', '15', '10', '10','ip7', '40', '20', '15','15']
let lastCurr = null;
const result = arr.reduce( ( res, curr, ix ) => {
if( 0 == ix % 5 ){
res[ curr ] = [];
lastCurr = curr;
}else
res[ lastCurr ].push( curr );
return res;
}, {} )
If your keys are always supposed to be isNaN and first value always corresponds to key, than you can do something like this, this will be more dynamic in case there are dynamic number of elements between two keys
const arr = ['ip6s+', '35', '15', '10', '10', 'ip7', '40', '20', '15', '15']
let getDesiredFormat = (arr) => {
let currentKey = arr[0]
let final = arr.reduce((op, inp) => {
if (isNaN(inp)) {
op[inp] = []
currentKey = inp
} else {
op[currentKey].push(inp)
}
return op
}, {})
return final
}
console.log(getDesiredFormat(arr))
If the array starts with an item that starts with "ip" and starting with that is the trigger for a new key in the object, you could use startswith.
This allows a variable number of items after ip.
const arr = ['ip6s+', '35', '15', '10', '10', 'ip7', '40', '20', '15', '15'];
const obj = {};
let currKey = arr.slice(0, 1);
arr.forEach(s => s.startsWith("ip") ? (currKey = s, obj[s] = []) : obj[currKey].push(s));
console.log(obj);
Use slice method, also the following example should work no matter how many elements in the array :
this should work also if there are elements before 'ip6s+' BUT the 'ip6s+' must always precede 'ip7'.
const arr = ['some', 'elemnts', 'in', 'front', 'ip6s+', '35', '15', 'abc', '80', '58', '10', '10', 'ip7', '40', '20', '15', '15', '100', 'xyz'],
l = arr.length,
ip6sIndex = arr.indexOf('ip6s+'),
ip7Index = arr.indexOf('ip7'),
obj = {};
obj[arr[ip6sIndex]] = arr.slice(ip6sIndex + 1, ip7Index); /** get the items after 'ip6s+' **/
obj[arr[ip7Index]] = arr.slice(-(l - ip7Index) + 1); /** get the items after 'ip7' **/
console.log(obj);

Create single object using two array

I have two arrays of same length
ids = [123, 456, 789, ...., 999];
names = ['foo', 'bar', ... , 'zzz'];
I want to create an array like
[ {id: 123, name: 'foo'}, {id: 123, name: 'bar'}, ..., {id: 999, name: 'zzz'} ]
I am trying to avoid forEach if possible.
Any suggestions?
Is map okay?
ids = [123, 456, 789, 999];
names = ['foo', 'bar', 'baz', 'zzz'];
result = ids.map(function(_, i) {
return {id: ids[i], name: names[i]}
});
console.log(result)
If you don't want to use any higher-order functions, then just do this:
var objects = [];
for (var i = 0; i < ids.length; i++) {
objects.push({id: ids[i], name: names[i]});
}
No need for forEach here. Use map which is similar to forEach.
var ids = [123, 456, 999];
var names = ['foo', 'bar', 'zzz'];
var result = ids.map(function (currentId, index) {
return {
id: currentId,
name: names[index]
};
});
console.log(result);
The forEach version would look like this (notice how similar they are):
var ids = [123, 456, 999];
var names = ['foo', 'bar', 'zzz'];
var result = [];
ids.forEach(function(currentId, index) {
result.push({
id: currentId,
name: names[index]
});
});
console.log(result);
The below code uses foreach but you dont need to handle it. I hope this will work for you.
ids = [123, 456, 789, 999];
names = ['foo', 'bar', 'zab', 'zzz'];
result = ids.map(function(_, i) {
return {id: ids[i], name: names[i]}
});
console.log(result)

Combining arrays in javascript into an array of hashes where one array is all the keys the rest are values

I have a couple of arrays that look like the following:
var foo = ['id', 'first', 'last'];
var student1 = ['1', 'sam', 'smith'];
var student2 = ['2', 'jon', 'murphy'];
Is there an efficient tool, perhaps using a library like underscore.js or vanilla javascript that will allow you to turn those three arrays into an object that looks like the following:
var finalObj = [
{'id' => 1, 'first' => 'sam', 'last' => 'smith'},
{'id' => 2, 'first' => 'jon', 'last' => 'murphy'}
];
A solution in plain Javascript
var foo = ['id', 'first', 'last'],
student1 = ['1', 'sam', 'smith'],
student2 = ['2', 'jon', 'murphy'],
result = [student1, student2].map(function (a) {
var o = {};
foo.forEach(function (k, i) {
o[k] = a[i];
});
return o;
});
console.log(result);
ES6 with Array#reduce
var keys = ['id', 'first', 'last'],
st1 = ['1', 'sam', 'smith'],
st2 = ['2', 'jon', 'murphy'],
result = [st1, st2].map(a => keys.reduce((o, k, i) => (o[k] = a[i], o), {}));
console.log(result);
Assuming that the order of the arrays always matters (it will always be ID, First, Last) - you could do something like:
var people = [student1, student2]; //create 2d array
var finalObj = people.reduce(function(final, person) {
var obj = {};
obj[foo[0]] = person[0]
obj[foo[1]] = person[1]
obj[foo[2]] = person[2]
final.push(obj);
return final;
}, []);
//[Objectfirst: "sam"id: "1"last: "smith"__proto__: Object, Objectfirst: "jon"id: "2"last: "murphy"__proto__: Object]
Underscore can help, for example:
_.map( [student1, student2], function(arr) {
return _.object(foo, arr);
})

Categories

Resources