How to dynamically create an object when looping an array? - javascript

I want to dynamically create an object with key value pairs from an array of object. How can this be done?
const arr= [
{key: 'a', value: '1'},
{key: 'b', value: '2'},
{key: 'c', value: '3'},
];
The result should look like this:
const obj = {
a: '1',
b: '2',
c: '3',
};

I would use reduce function for that.
The agg is an aggregator which aggregate our final result.
The item is representing each element in the array.
const arr= [
{key: 'a', value: '1'},
{key: 'b', value: '2'},
{key: 'c', value: '3'},
];
const result = arr.reduce((agg, item) => {
agg[item.key] = item.value
return agg
}, {})
console.log(result)
// { a: '1', b: '2', c: '3' }
The reduce() method executes a reducer function (that you provide) on each member of the array resulting in a single output value.

simple forEach will do the job
const arr= [
{key: 'a', value: '1'},
{key: 'b', value: '2'},
{key: 'c', value: '3'},
];
const obj = {};
arr.forEach(v=>{
obj[v.key] = v.value;
});
console.log(obj);

Very easy, probably a duplicate.
const arr= [
{key: 'a', value: '1'},
{key: 'b', value: '2'},
{key: 'c', value: '3'},
];
const obj = {};
for (let i = 0; i < arr.length; ++i) {
obj[arr[i].key] = arr[i].value
}
console.log(obj);

function parse(input){
return input.reduce(function(o,i){
o[i.key] = i.value;
return o;
},{});
}

Use Array.forEach() and the square brackets syntax to set the properties of the new object.
const arr = [
{key: 'a', value: '1'},
{key: 'b', value: '2'},
{key: 'c', value: '3'},
];
const obj = {};
arr.forEach(({key, value}) => obj[key] = value);
console.log(obj);

You can simply create an empty object and then create new properties on the fly, while iterating an array.
let obj = {};
for(let i = 0; i < arr.length; i++) {
obj[arr[i].key] = obj[i].value;
}

Related

how do I replace values of specific keys in an array of objects? javascript

I have an array of objects where I need to modify and replace values of specific keys:
arr = [ {key: 'a', value: 1}, {key: 'b', value: 2}, {key: 'c', value: 3}, {key: 'd', value: 4}, {key: 'e', value: 5}]
furthest I could figure was to filter arr.filter(i => i.key.includes('b','c','d')).map(i => i.value) but this would stop only on the first included filter and hold only one value (2). Id thought it would hold objects of keys b c d which values id then modify.
const arr = [{
key: 'a',
value: 1
}, {
key: 'b',
value: 2
}, {
key: 'c',
value: 3
}, {
key: 'd',
value: 4
}, {
key: 'e',
value: 5
}]
console.log(arr.filter(i => i.key.includes('b', 'c', 'd')).map(i => i.value))
Just iterate array and check if key of item matches desired keys and if so assign new value.
Because arr is an array of objects and objects are stored by reference you can alter the object directly without creating a new one.
const keys = ["a", "b", "c"];
const newValue = 1;
arr.forEach((item) => {
if (keys.includes(item.key)) {
item.value = newValue;
}
})

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

Javascript merge the values of 4 arrays into one object

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

Reduce complexity O^2 of comparison between list of objects

I have two list of objects:
list1 = [{value: 'X'}, {value: 'Y'}, ..., {value: 'Z'}];
list2 = [{value: 'A'}, {value: 'B'}, ..., {value: 'C'}];
I have this code that checks whether the values in list2 are in list1. If it is the code doesn't do anything, if not it should add to list1 (this will create a new list, list3). Which means I'm doing a union between the two list without keeping the repeated values.
for (let i = list2.length-1; i >= 0; i--) {
let item = list2[i];
let shared = false;
for (let j = list1.length-1; j >=0; j--) {
let childItem = list1[j];
if (item.value === childItem.value) {
shared = true;
break;
}
}
if (!shared) { newValues.push(item); }
}
list3 = list1.concat(newValues);
This works fine, but I was wondering if I could improve this O(n*m).
I'm not sure if the lists are always sorted by default, but from what I've seen both (list1 and list2) are always sorted by value.
Example:
var list1 = [{value: 'bar'}, {value: 'baz'}, {value: 'foo'}, {value: 'foz'}];
var list2 = [{value: 'bar'}, {value: 'foo'}, {value: 'test'}, {value: 'testz'}];
var list3 = union(list1, list2);
list3 = [{value: 'bar'}, {value: 'baz'}, {value: 'foo'}, {value: 'foz'}, {value: 'test'}, {value: 'testz'}];
Create a set of the values of list1, and Filter list2 by the values in the set before concating it to list1:
var list1 = [{value: 'bar'}, {value: 'baz'}, {value: 'foo'}, {value: 'foz'}];
var list2 = [{value: 'bar'}, {value: 'foo'}, {value: 'test'}, {value: 'testz'}];
const union = (list1, list2) => list1.concat(
list2.filter(function({ value }) { // filter list2
return !this.has(value); // filter out items which value is in the set
}, new Set(list1.map(({ value }) => value))) // the set of list1 values
);
const list3 = union(list1, list2);
console.log(list3);
You could use a single loop and store the value in a set for later check. Complexity: O(n).
var list1 = [{ value: 'X' }, { value: 'Y' }, { value: 'C' }, { value: 'Z' }],
list2 = [{ value: 'A' }, { value: 'B' }, { value: 'C' }, { value: 'D' }],
list3 = list1
.concat(list2)
.filter((s => ({ value }) => !s.has(value) && s.add(value))(new Set));
console.log(list3);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Split an object by each value in array inside of it

I have an object that contains a key and an array with some values inside of it.
var obj1 = {
'key': '1',
'values': ['a', 'b', 'c']
}
var obj2 = {
'key': '10',
'values': ['a', 'b']
}
I want to split this in other objects for each value in my values array to result something like this:
obj1 = 'key': '1', 'value':'a', 'index': '0';
obj2 = 'key': '1', 'value':'b', 'index': '1';
obj3 = 'key': '1', 'value':'c', 'index': '2';
obj4 = 'key': '10', 'value': 'a', 'index': '0';
obj5 = 'key': '10', 'value': 'b', 'index': '1';
Any ideas to do this?
Try this example
var brief = function(obj) {
var tmp = [],
i = 0,
l = obj.values.length;
while (i < l)
tmp.push({
key: obj.key,
index: i,
value: obj.values[i++]
});
return tmp;
};
var obj1 = brief({
key: '1',
values: ['a', 'b', 'c']
});
var obj2 = brief({
key: '2',
values: ['a', 'c']
});
document.write("<pre>");
document.write(JSON.stringify(obj1));
document.write("<br/>");
document.write(JSON.stringify(obj2));
document.write("</pre>");
Friend, it would be something like:
tmp = [];
obj1.values.forEach(function (e, i) {
tmp.push({key: obj1.key, value: e, index: i})
});
console.log(tmp);
assuming that you want
obj1 =[ { key: '1', value:'a', index: '0' },
{ key: '1', value:'b', index: '1'},
{ key: '1', value:'c', index: '2' }]
try
function splitArray( obj )
{
var output = [];
var keyValue = obj.key;
var values = obj.values;
for ( var counter = 0; counter < values.length; counter++ )
{
output.push( {
key : keyValue,
value : values[ counter ],
index : counter
} );
}
return output;
}
console.log( splitArray( obj1 ) );
function getTransformedObjects(obj) {
var ans = [];
if (obj.values) {
obj.values.forEach(function(value, index) {
var temp = {
'key': obj.key,
'value': value,
'index': index
};
ans.push(temp);
})
}
return ans;
}
//for display purpose
// usage
var obj1 = {
key: '1',
values: ['a', 'b', 'c']
}
console.log(getTransformedObjects(obj1));
$('.old').html(JSON.stringify(obj1))
$('.new').html(JSON.stringify(getTransformedObjects(obj1)));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div>old object</div>
<div class='old'></div>
<div>Trasnformed object</div>
<div class='new'></div>
Call the function passing the old object as parameter and get the array of objects in required format.

Categories

Resources