Making object from array with similar keys - javascript

I have an array like this:
var array = ['test1', 'test2', 'test3', 'test4']
I would like to make a new object from this array, and they should have the same keys. Desired outcome should be like this:
var objectFromArray = [
{ responsibilityName: "test1" },
{ responsibilityName: "test2" },
{ responsibilityName: "test3" },
{ responsibilityName: "test4"}
]
How is this possible in js?

Adjusted to your comment: you can use reduce and map to flatten the arrays within the array of objects.
[Edit based on your comment]
const arr = [
{ responsabilityName: ['test1', 'test2', 'test3', 'test4'],
somethingElse: [1, 2, 3, 4] } ];
const arrMapped = arr
.reduce( (mappedArr, obj) =>
Object.keys(obj)
.map( key => obj[key].map( prop => ({ [key]: prop }) ) )
.reduce( (p, n) => p.concat(n), [] ),
[] );
console.log(arrMapped);

Iterate over the array, create objects in the other one. As simple as that.
var array = ['test1', 'test2', 'test3', 'test4']
var objectFromArray = []
array.forEach((v)=>{objectFromArray.push({"responsibilityname":v})})

use array.map and assign the value to the object
DEMO
var array = ['test1', 'test2', 'test3', 'test4'];
var result = array.map(function(el) {
var obj = {};
obj['responsibilityname'] = el;
return obj;
})
console.log(array);
console.log(result);

Loop over the array and return a new object using map or forEach etc.
var array = ['test1', 'test2', 'test3', 'test4']
var arr = array.map(value => {
return {responsibilityName: value};
})
console.log(arr);

Related

how to create 2 arrays by running once on an array containing objects with the arrays matching the fields?

for example - lets say I have the array -
const array = [{name: "first", val: 1}, {name: "second", val: 2}]
I want to run once on that array and at the end of that run to have two arrays -
const arrayOne = ["first", "second"];
const arrayTwo = [1,2];
to get the first one is easy, but getting both at once?
I remember there was a way to do it but couldn't find it..
I'd appreciate any help!
Any looping logic will help
Array.reduce implementation will be like below
const array = [{ name: "first", val: 1 }, { name: "second", val: 2 }];
const [arrayOne, arrayTwo] = array.reduce((acc, curr) => {
const { name, val } = curr;
acc[0].push(name);
acc[1].push(val);
return acc;
}, [[], []]);
console.log(arrayOne, arrayTwo);
The function extractArrays is general-purpose and can be used in other cases as well.
function extractArrays(arr) {
const result = {};
for (obj of arr) {
for (key in obj) {
result[key] = (result[key] || []).concat([obj[key]]);
}
}
return result;
}
const array = [{name: "first", val: 1}, {name: "second", val: 2}];
const result = extractArrays(array);
const arrayOne = result.name;
const arrayTwo = result.val;
console.log(`arrayOne=${arrayOne}`);
console.log(`arrayTwo=${arrayTwo}`);
You can use Array.reduce to achieve this:
const array = [{name: "first", val: 1}, {name: "second", val: 2}]
const result = array.reduce((res, item) => {
res[0].push(item.name)
res[1].push(item.val)
return res
}, [[], []])
console.log(result)
thanks everyone!
but I think that the easiest, most readable code would be something like -
const itemArray = [], valArray = [];
data.map(({name, val})=> {
if(name) nameArray.push(name);
if(val) valArray.push(val);
})
because basically in 4 lines of code it's finished
thanks again everyone!
const array = [{name: "first", val: 1}, {name: "second", val: 2}]
const keys = [];
const values = [];
array.forEach(item=>{
keys.push(item.name);
values.push(item.val);
})
console.log(keys, values)
Use the Array.map function:
const array = [ { name: 'first', val: 1 }, { name: 'second', val: 2 } ]
let names = array.map(item => item.name)
let vals = array.map(item => item.val)
console.log(names)
console.log(vals)
The map function calls a callback function you provide on each element and constructs a new array from the results of that function.
If you are not familiar with arrow functions like:
item => item.name
... it is a short form for:
function (item) {
return item.name
}
You could even do it in one line:
let [ names, vals ] = [ array.map(item => item.name), array.map(item => item.val) ]

JavaScript nested map()

I have an array:
const array = [
{name: "abc", numbers:[1,2]},
{name: "def", numbers:[3,4]}
];
I want to use .map() to return a new array like:
[
{name:"abc", number:1},
{name:"abc", number:2},
{name:"def", number:3},
{name:"def", number:4}
]
What should I do?
It would be more performant to use forEach instead of map.
As #MohammadUsman's nice answer shows, the output of map has to be flattened before you can get the result you want. With forEach (which returns nothing), you can just append to the output array directly:
const data = [
{ name: "abc", numbers: [1,2] },
{ name: "def", numbers: [3,4] }
];
var result = [];
data.forEach(
({ numbers, ...rest }) => numbers.forEach(
n => result.push(Object.assign({number: n}, rest )))
);
console.log(result);
You can iterate over input array using .map() and use Object.assign() to generate new object and finally flat the array using .flat() to get the desired output.
const data = [
{ name: "abc", numbers: [1,2] },
{ name: "def", numbers: [3,4] }
];
const result = data.map(
({ numbers, ...rest }) => numbers.map(n => Object.assign({number: n}, rest ))
).flat();
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could take directly Array#flatMap with an inner mapping of new objects and get an array of objects.
const
array = [{ name: "abc", numbers:[1, 2] }, { name: "def", numbers:[3, 4] }],
result = array.flatMap(({ name, numbers }) => numbers.map(number => ({ name, number })));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use .reduce if flatmap not available. It is faster in your cases. Iteration will be only one time for each element.
const array = [
{ name: "abc", numbers: [1, 2] },
{ name: "def", numbers: [3, 4] },
];
const results = array.reduce((r, item) => {
r = r.concat(item.numbers.map((number) => ({ name: item.name, number })));
return r;
}, []);
console.log(results)
Here is a simple solution if you are up for using jquery...
const array = [
{name: "abc", numbers:[1,2]},
{name: "def", numbers:[3,4]}
];
var newArray = [];
$.each(array, function(k,v){
var strName = v.name;
$.each(v.numbers, function(key,value){
newArray.push({name: strName, number: value});
});
});
console.log(newArray);

Return a subset of an array of objects that matches a property of an another array of objects

inputs:
const parentArray = [
{id:1, name:'foo'},
{id:2, name:'bar'},
{id:4, name:'foobar'},
{id:6, name:'barfoo'}
]
const childArray = [
{parent_id:1, prop:'prop1'},
{parent_id:2, prop:'prop2'},
{parent_id:3, prop:'prop3'},
{parent_id:4, prop:'prop4'},
{parent_id:5, prop:'prop5'}
];
output:
const resultingArray = [
{id:1, name:'foo'},
{id:2, name:'bar'},
{id:4, name:'foobar'}
]
I want to compare the properties id and parent_id from both arrays and return a subset of parentArray for the matching properties
I've tried to filter them out but not having success, using lodash
You could take a Set for the wanted parents and filter the parent array.
var parents = [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }],
children = [{ parent_id: 1, prop: 'prop1' }, { parent_id: 3, prop: 'prop3' }],
wanted = new Set(children.map(({ parent_id }) => parent_id)),
result = parents.filter(({ id }) => wanted.has(id));
console.log(result);
You can do so with a combination of Array.filter() and Array.some() in the following way.
const resultingArray = parentArray
.filter(x => childArray.some( y => y.parent_id===x.id));
Check this JS bin
We can use a Set as a lookup table for the parent_id data from the child and then use Array.prototype.filter to filter through the parent entries and use Set#has to check if the id is contained in the Set:
const parentArray = [{id:1, name:'foo'},{id:2, name:'bar'}, {id:4, name:'foo'},{id:6, name:'bar'}]
const childArray = [
{parent_id:1, prop:'prop1'},
{parent_id:2, prop:'prop2'},
{parent_id:3, prop:'prop3'},
{parent_id:4, prop:'prop4'},
{parent_id:5, prop:'prop5'}
];
function findSubSet(){
const lookup = new Set(childArray.map(({parent_id}) => parent_id));
return parentArray.filter(p => lookup.has(p.id));
}
console.log(findSubSet(parentArray, childArray));
You can use reduce & findIndex. In the reduce callback use findIndex to check if there exist same id.If id exist it will return the index & if not then it will return -1. So if index is not -1 then you can push the value to accumulator(acc)
const parentArray = [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
const childArray = [{
parent_id: 1,
prop: 'prop1'
},
{
parent_id: 2,
prop: 'prop2'
},
{
parent_id: 3,
prop: 'prop3'
}
]
let filteredData = parentArray.reduce(function(acc, curr) {
let getIndexFromChild = childArray.findIndex(function(item) {
return curr.id === item.parent_id
});
if (getIndexFromChild !== -1) {
acc.push(curr)
}
return acc;
}, []);
console.log(filteredData)
As previously mentioned, your example is unclear, but filtering an array using another array, assuming you want to use the properties id from parentArray and parent_id from childArray, then I would use this:
resultingArray = childArray.filter(c=> parentArray.find(p => p.id === c.parentId);
You can use a mixture of filter and some to get the matching values:
const parentArray = [{id:1, name:'foo'},{id:2, name:'bar'}]
const childArray = [
{parent_id:1, prop:'prop1'},
{parent_id:3, prop:'prop3'}
]
let result = parentArray.filter(i => childArray.some(j => j.parent_id == i.id))
console.log(result)

How do you append an array of keys to object?

I have an array of strings and a params object like this. How do I create the params constant? Using either forEach, map, and or filter?
key = ['dog', 'car', 'cat'];
value = [ 3, 1, 2 ];
const params = {
item: {
[key]: value[0],
// more keys to be appended
}
}
Just looping through each value:
const key = ['dog', 'car', 'cat'];
const value = [ 3, 1, 2 ];
const item = {};
key.forEach((k, i) => { item[k] = value[i]; });
const parmas = {};
parmas.item = item;
console.log(parmas);
You can set an object's keys using the following syntax:
obj[key] = value
So in you case, you could do something like:
key = ['dog', 'car', 'cat'];
value = [ 3, 1, 2 ];
var params = {
item : {}
}
for (var i=0; i<key.length;i++){
params.item[key[i]] = value[i];
}
You could do it this way:
value.reduce((acc, val, index) => (acc[key[index]] = val, acc), {});
This produces:
{dog: 3, car: 1, cat: 2}

Combine values of inner object using JavaScript or Underscore

I have an array as follows:
const arr = [{
name: 'XYZ',
values: [1, 2, 3]
}, {
name: 'ABC',
values: [5]
}, {
name: 'XYZ',
values: [4, 5, 6]
}, {
name: 'ABC',
values: [8, 9]
}];
I'm using underscore js and trying to transform as follows:
const result = [{
name: 'XYZ',
values: [1, 2, 3, 4, 5, 6]
}, {
name: 'ABC',
values: [5, 8, 9]
}]
I was able to group by name and trying to loop in, but not sure how do I merge values. So far this is what I've done:
_.chain(arr)
.groupBy((item) => item.name)
// I don't know what to do here
.value();
With ES6, you can use Array#reduce with a Map to get the desired result:
const arr = [{"name":"XYZ","values":[1,2,3]},{"name":"ABC","values":[5]},{"name":"XYZ","values":[4,5,6]},{"name":"ABC","values":[8,9]}];
const result = [...arr.reduce((m, { name, values }) => {
const el = m.get(name) || { name, values: [] }; // get the result object from the map or create a new one
el.values.push(...values); // push the current values to the result object values property
return m.set(name, el); // add the result object to the map, and return the map
}, new Map()).values()]; // get the map values, and spread to an array
console.log(result);
Using underscore:
const arr = [{"name":"XYZ","values":[1,2,3]},{"name":"ABC","values":[5]},{"name":"XYZ","values":[4,5,6]},{"name":"ABC","values":[8,9]}];
const result = _.chain(arr)
.groupBy('name') // group by name
.mapObject((group, name) => ({ // map each group to a new object
name,
values: _.flatten(_.pluck(group, 'values')) // get all values arrays, and flatten to a single array
}))
.values() // convert the groups object to an array
.value();
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
Maybe, you can try vanilla Javascript way.
var result = [];
arr.forEach((item) => {
let currObj = result.find((item2) => item2.name === item.name);
if(currObj){
currObj.values = currObj.values.concat(item.values);
} else {
result.push(JSON.parse(JSON.stringify(item)));
}
})

Categories