Get single property array from an array of objects - javascript

I have this array of objects and I want to get all the controls from this to another array:
this.formModel = {
sections: [
{
title: 'Section 01',
controls: [
new FormControlInput({
key: 'name 01',
label: 'Name 01'
}),
new FormControlSelect({
key: 'abc',
label: 'Abc'
})
]
},
{
title: 'Section 02',
controls: [
new FormControlInput({
key: 'name 02',
label: 'Name 02'
})
]
}
]
};
I am using map for this but I am not getting single array, I am getting array of arrays:
this.formModel.sections.map(function (x) { return x.controls; })
Getting this:
[
{
[{
key: 'name 01',
label: 'Name 01'
},
{
key: 'abc',
label: 'Abc'
}]
},
{
[{
key: 'name 02',
label: 'Name 02'
}]
}
]
What I want is this:
[
{
key: 'name 01',
label: 'Name 01'
},
{
key: 'abc',
label: 'Abc'
},
{
key: 'name 02',
label: 'Name 02'
}
]

You just need to flatten your array after mapping:
var obj = {
sections: [{
title: 'Section 01',
controls: [
{ key: 'name 01', label: 'Name 01' },
{ key: 'abc', label: 'Abc' }
]
}, {
title: 'Section 02',
controls: [
{ key: 'name 02', label: 'Name 02' }
]
}
]
};
var mapped = obj.sections.map(function (x) { return x.controls; });
var flattened = [].concat.apply([], mapped);
console.log(flattened);
To simplify your example:
// This is your structure:
var sections= [{
controls: [{}, {}] // C1
}, {
controls: [{}] // C2
}
];
// With the map, grabbing each `controls` property, and using that as an entry in your array:
var mapped = sections.map(function (x) { return x.controls; });
console.log(mapped);
// [[{},{}],[{}]]
// ^ C1 ^ C2
// We need to remove that extra layer of arrays:
var flattened = [].concat.apply([], mapped);
console.log(flattened);

You can use reduce to flatten the hierarchy
formModel.sections
.map(x => x.controls)
.reduce((prev, current) => prev.concat(current), [])

Use reduce instead of map:
let formModel = {
sections: [
{
title: 'Section 01',
controls: [
{
key: 'name 01',
label: 'Name 01'
},
{
key: 'abc',
label: 'Abc'
}
]
},
{
title: 'Section 02',
controls: [
{
key: 'name 02',
label: 'Name 02'
}
]
}
]
};
let result = formModel.sections.reduce((res, section) => {
return res = res.concat(section.controls);
}, []);
console.log(result);

Related

Push value to multiple arrays

const array = [{
id: 1,
name: 'test',
attrs: [{
name: 'Attribute 1',
description: 'Description 1',
}],
values: [{
name: 'value 1',
attrs: [{
name: 'Attribute 1',
type: 'Type 1',
},
{
name: 'Attribute 2',
type: 'Type 2',
},
],
}, ],
}, ];
const newArray =
array.map((item) => {
return {
...item,
isNegative: true
};
});
console.log(newArray);
I receive data as displayed in the const array. I need to push a value 'isNegative' to array[].attrs and to each values.attrs. I'm only able to do it to the array[].attrs. How can I do it to the others?
You're only mapping over the top-level array. If you need to map over the arrays within each object, that's another call to .map(). For example:
const array = [{
id: 1,
name: 'test',
attrs: [{
name: 'Attribute 1',
description: 'Description 1',
}],
values: [{
name: 'value 1',
attrs: [{
name: 'Attribute 1',
type: 'Type 1',
},
{
name: 'Attribute 2',
type: 'Type 2',
},
],
}, ],
}, ];
const newArray =
array.map((item) => {
return {
...item,
isNegative: true,
attrs: item.attrs.map((attr) => {
return {
...attr,
isNegative: true
}
})
};
});
console.log(newArray);
Same with the values property, any array within objects in values, etc. Any array that you want to map to a new structure, call .map() on it.

How to deep merge two collections by duplicate key in JavaScript/Lodash?

I would like to merge two collections by duplicate key in javascript, here is example collections:
let collection1 = [
{
title: 'Overview',
key: 'Test-overview',
isLeaf: true
},
{
title: 'Folder 1',
key: 'Test-Folder_1',
children: [
{
title: 'Folder 1 Content 1',
key: 'Test-Folder_1-Content_1',
isLeaf: true,
},
],
}
]
let collection2 = [
{
title: 'Folder 1',
key: 'Test-Folder_1',
children: [
{
title: 'Sub Folder 1 in Folder 1',
key: 'Test-Folder_1-Sub_Folder_1',
children: [
{
title: 'Sub Folder 1 Conetent',
key: 'Test-Folder_1-Sub_Folder_1-Content',
isLeaf: true,
},
],
},
],
}
]
and this is example output:
let exampleOutput = [
{
title: 'Overview',
key: 'Test-overview',
isLeaf: true
},
{
title: 'Folder 1',
key: 'Test-Folder_1',
children: [
{
title: 'Folder 1 Content 1',
key: 'Test-Folder_1-Content_1',
isLeaf: true,
},
{
title: 'Sub Folder 1 in Folder 1',
key: 'Test-Folder_1-Sub_Folder_1',
children: [
{
title: 'Sub Folder 1 Conetent',
key: 'Test-Folder_1-Sub_Folder_1-Content',
isLeaf: true,
},
],
},
],
}
]
How can I achieve this output with Javascript? I tried with Lodash _.merge and _.mergeWith but the output is not what I want.
I also tried this link: Merge JavaScript objects in array with same key answer by #BenG but it only able to merge the first layer of the collections, which mean if I have collection3 that contain another content in Test-Folder_1-Sub_Folder_1, it will be replaced by the first layer of the new collection.
You can use recursion:
let collection1 = [{title: 'Overview', key: 'Test-overview', isLeaf: true}, {title: 'Folder 1', key: 'Test-Folder_1', children: [{title: 'Folder 1 Content 1', key: 'Test-Folder_1-Content_1', isLeaf: true, },],}]
let collection2 = [{title: 'Folder 1', key: 'Test-Folder_1', children: [{title: 'Sub Folder 1 in Folder 1', key: 'Test-Folder_1-Sub_Folder_1', children: [{title: 'Sub Folder 1 Conetent', key: 'Test-Folder_1-Sub_Folder_1-Content', isLeaf: true,},],},],}]
function merge(collections){
var formed = {}
for (var i of collections){
key = JSON.stringify(Object.keys(i).filter(x => x != 'children').map(x => [x, i[x]]))
if (!(key in formed)){
formed[key] = []
}
formed[key] = [...formed[key], ...('children' in i ? i.children : [])]
}
return Object.keys(formed).map(x => ({...Object.fromEntries(JSON.parse(x)), ...(formed[x].length ? {'children':merge(formed[x])} : {})}))
}
console.log(merge([...collection1, ...collection2]))

How can I move an object from one array to another array with function?

Hello everyone and dear friends. While learning React, I noticed that I lacked javascript and I started to learn javascript carefully.
Let me try to tell you what I am trying to do. I have two arrays. I want to move one of the elements of the instance element in array1 to the instance in array2.
How can I do it? Which method would you recommend? Does it work to splice the element and push it down? How can a function be written for this? I would be glad if you help.
const array1 = [
{
id: '1',
instance: [
{ id: '34', title: 'Example 1' },
{ id: '35', title: 'Example 2' },
{ id: '36', title: 'Example 3' }, // delete this object from here
},
{
id: '2',
instance: [
{ id: '37', title: 'Example 4' }
],
},
];
I want to move the element I deleted into this array.
const array2 = [
{
id: '1',
instance: [
{ id: '34', title: 'Example 1' },
{ id: '35', title: 'Example 2' },
},
{
id: '2',
instance: [
{ id: '37', title: 'Example 4' },
// { id: '36', title: 'Example 3' }, // i want to move here
],
},
];
You can use pop() to remove last element from array.
const array1 = [{
id: '1',
instance: [{
id: '34',
title: 'Example 1'
},
{
id: '35',
title: 'Example 2'
},
{
id: '36',
title: 'Example 3'
}
],
}, {
id: '2',
instance: [{
id: '37',
title: 'Example 4'
}],
}, ];
let tmp = array1[0].instance[2];
array1[0].instance.pop();
array1[1].instance.push(tmp);
console.log(array1);
const array1 = [
{
id: '1',
instance: [
{ id: '34', title: 'Example 1' },
{ id: '35', title: 'Example 2' },
{ id: '36', title: 'Example 3' }, // delete this object from here
]
},
{
id: '2',
instance: [
{ id: '37', title: 'Example 4' }
]
}
];
const array2 = [
{
id: '1',
instance: [
{ id: '34', title: 'Example 1' },
{ id: '35', title: 'Example 2' },
]
},
{
id: '2',
instance: [
{ id: '37', title: 'Example 4' },
// { id: '36', title: 'Example 3' }, // i want to move here
]
}
];
//answer
function transfer(fromArr,index,toArr){
toArr.push(fromArr.splice(index,1))
}
transfer(array1[0].instance,2,array2[1].instance)
console.log("first array",array1)
console.log("second array",array2)
const array1 = [
{
id: '1',
instance: [
{ id: '34', title: 'Example 1' },
{ id: '35', title: 'Example 2' },
{ id: '36', title: 'Example 3' },] // delete this object from here
},
{
id: '2',
instance: [
{ id: '37', title: 'Example 4' }
],
},
];
var temp = array1[0]
array1.splice(0,1);
const array2 = [
{
id: '1',
instance: [
{ id: '34', title: 'Example 1' },
{ id: '35', title: 'Example 2' },]
},
{
id: '2',
instance: [
{ id: '37', title: 'Example 4' },
// { id: '36', title: 'Example 3' }, // i want to move here
],
},
];
array2.push(temp)
console.log(array2)
First thing, your object has wrong brackets. Here is a fixed version for array1
const array1 = [
{
id: '1',
instance: [
{ id: '34', title: 'Example 1' },
{ id: '35', title: 'Example 2' },
{ id: '36', title: 'Example 3' }, // delete this object from here
]
},
{
id: '2',
instance: [
{ id: '37', title: 'Example 4' }
],
},
];
Now remove one element, IDK how you're getting the key for this, so I ill just declare it as constant, up to you to modify
let key = 0;
let Nested_key = 2;
let removed = array1[key].instance.splice(Nested_key,1) //1st param= 0: the position, 2nd param = 1 number of elements to rm starting from param1 position
Now we removed the element, and it is stored in removed (an array of length=1), just insert it now
array2[key].instance.push(removed[0]);
Judging by your post, it Seems like you knew already what splice and push are and what they do (the name are quite clear and intuitive). Feel free to ask for clarifications if there is any part that you don't understand in my answer

How to get values from one array of objects into another array of objects

I wanted to get values from one array of object with keys and values into another array of objects with the same keys.
const array1 = [{
key1: 7,
key2: 1,
key3: 37,
}];
const array2 = [
{
title: 'Some Title 1',
key: 'key1',
number: '',
icon: require('../../assets/some2.png')
},
{
title: 'Some Title 2',
key: 'key2',
number: '',
icon: require('../../assets/some1.png')
},
{
title: 'Some Title 3',
key: 'key3',
number: '',
icon: require('../../assets/some3.png')
},
];
I have tried using Object.keys to get all the keys from array1 object.
const keys = Object.keys(obj);
keys.map((key) => {
if (array2[key] === key) {
// console.log('card detail matching');
// add to the array 2 with value
}
})
but after a point its doesn't makes sense.
Expected array
const resultArray = [
{
title: 'Some Title 1',
key: 'key1',
number: 7,
icon: require('../../assets/some2.png')
},
{
title: 'Some Title 2',
key: 'key2',
number: 1,
icon: require('../../assets/some1.png')
},
{
title: 'Some Title 3',
key: 'key3',
number: 37,
icon: require('../../assets/some3.png')
}
]
I expect the output to be the values of the key would be entered in array2 in the 'number' key.
You could map a new array by taking the key as accessor for keys.
const
array1 = [{ key1: 7, key2: 1, key3: 37 }],
array2 = [{ title: 'Some Title 1', key: 'key1', number: '', icon: '../../assets/some2.png' }, { title: 'Some Title 2', key: 'key2', number: '', icon: '../../assets/some1.png' }, { title: 'Some Title 3', key: 'key3', number: '', icon:'../../assets/some3.png' }],
result = array2.map(o => Object.assign({}, o, { number: array1[0][o.key] }));
console.log(result);
Below code help you:-
const array1 = {
key1: 7,
key2: 1,
key3: 37,
};
const array2 = [
{
title: 'Some Title 1',
key: 'key1',
number: '',
icon: require('../../assets/some2.png')
},
{
title: 'Some Title 2',
key: 'key2',
number: '',
icon: require('../../assets/some1.png')
},
{
title: 'Some Title 3',
key: 'key3',
number: '',
icon: require('../../assets/some3.png')
},
];
array2.forEach(item=>{
item.number=array1[item.key]
})
You can iterate through each object from array2 and add the number value fetching from array1
const array1 = [{
key1: 7,
key2: 1,
key3: 37,
}];
const array2 = [
{
title: 'Some Title 1',
key: 'key1',
number: '',
icon: '../../assets/some2.png'
},
{
title: 'Some Title 2',
key: 'key2',
number: '',
icon: '../../assets/some1.png'
},
{
title: 'Some Title 3',
key: 'key3',
number: '',
icon: '../../assets/some3.png'
},
];
array2.forEach(e => e.number = array1[0][e.key]);
console.log(array2)
const array1 = [{
key1: 7,
key2: 1,
}];
const array2 = [
{
title: 'Some Title 1',
key: 'key1',
number: '',
icon: '../../assets/some2.png'
},
{
title: 'Some Title 2',
key: 'key2',
number: '',
icon: '../../assets/some1.png'
},
{
title: 'Some Title 3',
key: 'key3',
number: '',
icon: '../../assets/some3.png'
},
];
const resultArray = array2.filter(item => array1[0][item.key]);
console.log(resultArray);
You can filter to get the result.
This should work for you.
const keys = [
{
key1: 7,
key2: 1,
key3: 37,
},
{
key4: 7,
key5: 1,
key6: 37,
}
];
const array2 = [
{
title: 'Some Title 1',
key: 'key4',
number: ''
},
{
title: 'Some Title 2',
key: 'key2',
number: ''
},
{
title: 'Some Title 3',
key: 'key3',
number: ''
}
];
function populateArrayData (arr, propToCompare, propToReplace, keysObj) {
let populatedArray = [];
if (Array.isArray(arr)) {
populatedArray = arr.map((item) => {
if (checkIfKeyExists(item[propToCompare], keysObj)) {
item[propToReplace] = keysObj[item[propToCompare]];
}
return item;
});
}
return populatedArray;
}
function flattenAllKeys (keys) {
let flattenedKeysObj = {};
if (Array.isArray(keys)) {
flattenedKeysObj = keys.reduce((acc, keysObj) => {
acc = {...acc, ...keysObj};
return acc;
}, {});
}
return flattenedKeysObj;
}
function checkIfKeyExists(key, keysObj) {
return (keysObj[key]!== undefined && keysObj[key]!== null);
}
let flattenedKeys = flattenAllKeys(keys);
console.log(populateArrayData(array2, 'key', 'number', flattenedKeys));

Merging Arrays of Objects by Key/Values

I have two separate arrays of objects that I need to merge based if a specific key value matches. Might make more sense after analyzing the data:
Array 1
let categories = [
{ id: 5, slug: 'category-5', items: [] },
{ id: 4, slug: 'category-4', items: [] },
{ id: 3, slug: 'category-3', items: [] },
]
Array 2
let items = [
{ id: 5, data: [{ title: 'item title', description: 'item description' }] },
{ id: 5, data: [{ title: 'item title 2', description: 'item description 2' }] },
{ id: 4, data: [{ title: 'item title 4', description: 'item description 4' }] },
]
Expected Output
let mergedOutput = [
{ id: 5, slug: 'category-5',
items: [
{ title: 'item title', description: 'item description' },
{ title: 'item title 2', description: 'item description 2' }
]
},
{ id: 4, slug: 'category-4',
items: [
{ title: 'item title 4', description: 'item description 4' },
]
},
{ id: 3, slug: 'category-3', items: [] },
]
So....I need to add Array 2 to Array 1 if their id's match.
Array 1 will stay the same, but if Array 2 matches, the items property of Array 1 (empty) will be replaced by the data property of Array 2
I know this is a pretty basic / and redundant question, but I can't find the resources for my use case / object structure.
I was able to easily group arrays with lodash -- so if there is a similar solution with that library -- that would good! Or just some direction would suffice.
Thanks in advance!
You can loop first array and then use filter to get objects with same id as current element and add that items to current object.
let categories = [
{ id: 5, slug: 'category-5', items: [] },
{ id: 4, slug: 'category-4', items: [] },
{ id: 3, slug: 'category-3', items: [] },
]
let items = [
{ id: 5, data: [{ title: 'item title', description: 'item description' }] },
{ id: 5, data: [{ title: 'item title 2', description: 'item description 2' }] },
{ id: 4, data: [{ title: 'item title 4', description: 'item description 4' }] },
]
categories.forEach(function(e) {
var i = items.filter(a => a.id == e.id).map(a => a.data);
e.items = i;
})
console.log(categories)
You could reduce the items into categories:
let res = items.reduce((a, b) => {
let it = a.find(e => e.id === b.id);
if (! it) return a;
it.items = it.items.concat(b.data);
return a;
}, categories);
let categories = [{
id: 5,
slug: 'category-5',
items: []
},
{
id: 4,
slug: 'category-4',
items: []
},
{
id: 3,
slug: 'category-3',
items: []
},
];
let items = [{
id: 5,
data: [{
title: 'item title',
description: 'item description'
}]
},
{
id: 5,
data: [{
title: 'item title 2',
description: 'item description 2'
}]
},
{
id: 4,
data: [{
title: 'item title 4',
description: 'item description 4'
}]
},
];
let res = items.reduce((a, b) => {
let it = a.find(e => e.id === b.id);
if (! it) return a;
it.items = it.items.concat(b.data);
return a;
}, categories);
console.log(res);
It might be faster to get the ids in an object first, so we don't have to use find on the same id many times:
function merge(result, toMerge, mergeInto) {
let i = 0, hm = {};
for (let {id} of categories) {
hm[id] = i;
i++;
}
return toMerge.reduce((a,b) => {
let it = a[hm[b.id]];
if (!it) return a;
it[mergeInto] = it[mergeInto].concat(b.data);
return a;
}, result);
}
let categories = [
{ id: 5, slug: 'category-5', items: [] },
{ id: 4, slug: 'category-4', items: [] },
{ id: 3, slug: 'category-3', items: [] },
];
let items = [
{ id: 5, data: [{ title: 'item title', description: 'item description' }] },
{ id: 5, data: [{ title: 'item title 2', description: 'item description 2' }] },
{ id: 4, data: [{ title: 'item title 4', description: 'item description 4' }] },
];
function merge(result, toMerge, mergeInto) {
let i = 0, hm = {};
for (let {id} of categories) {
hm[id] = i;
i++;
}
return toMerge.reduce((a,b) => {
let it = result[hm[b.id]];
if (!it) return a;
it[mergeInto] = it[mergeInto].concat(b.data);
return a;
}, result);
}
console.log(merge(categories, items, 'items'));
I would make the categories as hash map and the key would be the id and iterate over all the items only.
then you get O(N) solution.

Categories

Resources