Situation is simple: Make a double map to deconstruct into a single Array rather then multiple.
The Data example:
const data = [
{
name: 'testa',
values: [
{ index: '1993', value: 5 },
{ index: '1994', value: 6 },
],
},
{
name: 'testb',
values: [
{ index: '1991', value: 8 },
{ index: '1992', value: 3 },
{ index: '1993', value: 9 },
],
},
];
A method should take this array and convert into a single array of this data (order dosent matter):
const proccessedData = [
{ index: '1993', value: 5, name: 'testa' },
{ index: '1994', value: 6, name: 'testa' },
{ index: '1991', value: 8, name: 'testb' },
{ index: '1992', value: 3, name: 'testb' },
{ index: '1993', value: 9, name: 'testb' },
];
I achieve this by using this method I created:
const getData = (obj) => {
const data = [];
obj.map(({ values, name }) => {
data.push(...values.map(({ index, value }) => ({ index, value, name })));
});
return data;
};
And it works BUT I disliake it because of (read below in The Problem):
THE PROBLEM
It depends on const data = [] to do a data.push(...). Would prefer that it would auto decontruct it so a method would look something like this:
const getData = (obj) =>
obj.map(({ values, name }) => values.map(({ index, value }) => ({ index, value, name })));
Basically, on a single line, without the use of another variable BUT the return structure would remain as mentioned above. But using thtis method it returns an array with 2 different arrays inside.
It is being used inside another structure like so:
const config = {
data: getData(data),
height: 400,
xField: "index",
yField: "value",
seriesField: "name"
};
So it has to return deconstructed array already without involving any other variables. Yes, I could leave it as it is right now, but I wanna do the deconstruction way as its cleaner, in my opinion, and I would learn something new.
NOTE doing data: {...getData(data)}, or data: [...getData(data)], does Not work.
A working example to play around: https://codesandbox.io/s/bold-cannon-fwot6?file=/src/App.js:690-826
This would be simpler with flatMap:
const data = [
{
name: 'testa',
values: [
{ index: '1993', value: 5 },
{ index: '1994', value: 6 },
],
},
{
name: 'testb',
values: [
{ index: '1991', value: 8 },
{ index: '1992', value: 3 },
{ index: '1993', value: 9 },
],
},
];
proccessedData = data.flatMap(d => d.values.map(v => ({...v, name: d.name})))
console.log(proccessedData)
You can also try this: I am using here map function twice, and then flatten into a single array, The flatMap method is identical to a map followed by a call to a flat of depth 1.
const data = [
{
name: 'testa',
values: [
{ index: '1993', value: 5 },
{ index: '1994', value: 6 },
],
},
{
name: 'testb',
values: [
{ index: '1991', value: 8 },
{ index: '1992', value: 3 },
{ index: '1993', value: 9 },
],
},
];
const dataProcess = data
.map((d) =>
d.values.map((v) => ({...v, name: d.name}))
).flat();
console.log(dataProcess);
Related
Does anyone know how I can create a new array from existing array with unique joined values from existing array?
const originalArray = [
[
{ value: 'red', id: 99 },
{ value: 'blue', id: 100 },
],
[
{ value: 'small', id: 101 },
{ value: 'medium', id: 102 },
],
[
{ value: 'modern', id: 103 },
{ value: 'classic', id: 104 },
],
];
//
//
const newArrayBasedOnOriginalArray = [
{ value: 'red/small/modern' },
{ value: 'red/small/classic' },
{ value: 'red/medium/modern' },
{ value: 'red/medium/classic' },
{ value: 'blue/small/modern' },
{ value: 'blue/small/classic' },
{ value: 'blue/medium/modern' },
{ value: 'blue/medium/classic' },
];
I calculated that the length of the new array should always be as following:
// length of new array
const lengthOfNewArray = originalArray
.map((value) => {
return value.length;
})
.reduce((current, old) => {
return current * old;
});
//
//
console.log('length of new array:', lengthOfNewArray); // 8
You can do it recursively
const originalArray = [
[
{ value: 'red', id: 99 },
{ value: 'blue', id: 100 },
],
[
{ value: 'small', id: 101 },
{ value: 'medium', id: 102 },
],
[
{ value: 'modern', id: 103 },
{ value: 'classic', id: 104 },
],
];
const getPossibleCombination = (currentValue, arraysRemaining) => {
if(arraysRemaining.length === 0) return currentValue
const values = []
const firstArray = arraysRemaining[0]
firstArray.forEach(({value}) => {
values.push(getPossibleCombination(`${currentValue}/${value}`, arraysRemaining.slice(1, arraysRemaining.length)))
})
return values.flat()
}
const values = getPossibleCombination('', originalArray)
console.log(values)
In this case, you do not necessarily need recursion. Array.reduce() greatly does the job:
const originalArray = [
[
{ value: 'red', id: 99 },
{ value: 'blue', id: 100 },
],
[
{ value: 'small', id: 101 },
{ value: 'medium', id: 102 },
],
[
{ value: 'modern', id: 103 },
{ value: 'classic', id: 104 },
],
];
const newArray = originalArray
.map(elem => elem.map(({value}) => value))
.reduce((acc, cur) => acc.flatMap(seq => cur.map(part => `${seq}/${part}`)))
.map(elem => ({value: elem}))
console.log(newArray)
Aside from the initial and final map(), used to simplify the input objects, what I am doing is continuously combining the accumulator with the next sub-array.
For each object in the sub-array I duplicate every object in the accumulator, using the nested map(). flatMap() is used to keep the accumulator flat, with a simple map() the accumulator depth would increase every time we visit a new sub-array.
First of all if values in each of your arrays is unique then the concatenated values will be unique as well. After you make sure values are unique you can use this code to create combinations of strings:
const newArrayBasedOnOriginalArray = originalArray.reduce(
(acc, el) =>
el.flatMap(({ value }) =>
acc.length ? acc.map((str) => str + "/" + value) : value
),
[]
).map(value=>({value});
This question already has answers here:
From an array of objects, extract value of a property as array
(24 answers)
get values from object and push into array javascript
(3 answers)
Closed 1 year ago.
I would like to get the values of the attribute value in a new array. For the following example, the result would be: ["Plumbing", "Electrical", "Fencing"]
const arr = [
{ label: "Plumbing", value: "Plumbing" },
{ label: "Electrical", value: "Electrical" },
{ label: "Fencing", value: "Fencing" },
];
I mean something like: newArray = currentArray forEach Get Value
You can easily get the value of all label using map
const arr = [
{ label: "Plumbing", value: "Plumbing" },
{ label: "Electrical", value: "Electrical" },
{ label: "Fencing", value: "Fencing" },
];
const result = arr.map((o) => o.value);
console.log(result);
You can also destructure to make it more succinct
const result = arr.map(({ value }) => value);
const arr = [
{ label: "Plumbing", value: "Plumbing" },
{ label: "Electrical", value: "Electrical" },
{ label: "Fencing", value: "Fencing" },
];
const result = arr.map(({ value }) => value);
console.log(result);
You can add your values to a new array using forEach like so :
const arr = [
{ value: "Plumbing", label: "Plumbing" },
{ label: "Electrical", value: "Electrical" },
{ label: "Fencing", value: "Fencing" },
];
var newArr = []
arr.forEach(e => newArr.push(e.value))
console.log(newArr)
Or like #decpk said in comment you could simply use map() like so
const arr = [
{ value: "Plumbing", label: "Plumbing" },
{ label: "Electrical", value: "Electrical" },
{ label: "Fencing", value: "Fencing" },
];
var newArr = arr.map(e => e.value)
console.log(newArr)
There is an object and an array.
list: [
{
oldData: {
title: 'abc',
id: 1,
date: '1982-09-30',
budget: 250000,
},
newData: [
{
key: 1,
data: null,
value: 5,
},
{
key: 2,
data: null,
value: 22,
},
...
],
},
{
oldData: {
title: 'blablablaaaaa',
id: 2,
date: '2012-02-23',
budget: 350000,
},
newData: [
{
key: 1,
data: null,
value: 35,
},
{
key: 2,
data: null,
value: 41,
},
...
],
},
... some more datas...
]
as above, There is more data of the same type.
I need to use oldData and newData together, so I want to combine the two.
How can I combine oldData and newData so that there are multiple sets of oldData and newData pairs?
for example, [{ combineData: {...} }, { combineData: {...} }, ... }] here.
I know how to combine array and array, object and object, but I do not know how to do that.
Is there any good solution?
Your desired result is unclear, but you did say you wanted old/new pairs. This answer is different than the others in that it produces an array of combined data objects made of old/new pairs, where the oldData values are duplicated in order to appear alongside each corresponding newData value within its list item.
your original data after the first question update:
let list = [
{
oldData: { title: 'abc', id: 1, date: '1982-09-30', budget: 250000 },
newData: [
{ key: 1, data: null, value: 5 },
{ key: 2, data: null, value: 22 },
//...
],
},
{
oldData: { title: 'blablablaaaaa', id: 2, date: '2012-02-23', budget: 350000 },
newData: [
{ key: 1, data: null, value: 35 },
{ key: 2, data: null, value: 41 },
//...
],
},
//... some more datas...
];
This code maps each {old,new[]} list item into arrays of pairs [{old,new}, {old,new}, ...] that are combined in the final reduce() call:
var combinedDatas = list
.map(listItem => listItem.newData.map(newItem => ({
oldData: listItem.oldData,
newData: newItem
})))
.reduce();
console.log(JSON.stringify(oldNewCombos, null, 4));
produces a list of denormalized pairs:
[
{ list[0].oldData, list[0].newData[0] },
{ list[0].oldData, list[0].newData[1] },
//...rest of list[0] oldData with newData[n] combos
{ list[1].oldData, list[1].newData[0] },
{ list[1].oldData, list[1].newData[1] },
//...rest of list[1] oldData with newData[n] combos
{ list[2].oldData, list[2].newData[0] },
{ list[2].oldData, list[2].newData[1] },
//...rest of list[2] oldData with newData[n] combos
//...
]
You can use map() on the array. And use Object.assign() and spread operator to combine all the properties of all the elements in newData into one object.
const arr = [
{
oldData: {
a:10,
b:20
},
newData: [
{
c:30,
d:40
},
{
e:50,
f:60
}
],
}
]
const res = arr.map(x => ({combinedData:{...x.oldData, ...Object.assign({}, ...x.newData)}}))
console.log(res)
You can map over the array and use object destructuring (...object) to create a new, combined object:
const data = [
{
oldData: {
foo: 'lorem',
},
newData: {
bar: 'ipsum',
},
},
{
oldData: {
foo: 'dolor',
},
newData: {
bar: 'sit amet',
},
},
];
const combined = data.map(record => ({...record.oldData, ...record.newData}));
console.log(combined);
This will overwrite duplicate keys however, so something like:
{
oldData: {
message: 'a',
},
newData: {
message: 'b',
},
}
will become:
{
message: 'b',
}
This question already has answers here:
Build tree array from flat array in javascript
(34 answers)
Closed 4 years ago.
I currently have a flat array of objects which I am trying to convert to a nested array of objects. I would like to reuse this function throughout my application - whatever the final depth of the array - so I believe a recursive function would be more appropriate.
My attemps so far I have been a combination of sort + reduce with no success.
It would be much appreciated if you could help me write a clean function for my app !
Initial Array - Flat list of objects
const data = [
{ index: 0, parentKey: '-LLnMWy69vACjys0QIGH', type: 'options', name: 'OPTION_1', key: '-LLnOxg5hsDYR-PcfjBT' },
{ index: 1, parentKey: '-LLnMWy69vACjys0QIGH', type: 'options', name: 'OPTION_2', key: '-LLnP-O6TyHxIpPk9bCU' },
{ index: 0, parentKey: '-LLnLuLt6cn-vBpMWv-u', type: 'collections', name: 'COLLECTION_1', key: '-LLnMWy69vACjys0QIGH' },
{ index: 1, parentKey: '-LLnLuLt6cn-vBpMWv-u', type: 'collections', name: 'COLLECTION_2', key: '-LLnMYNyJmhSCPB-8lL1' },
{ index: 0, name: 'CONFIGURATOR_1', key: '-LLnLuLt6cn-vBpMWv-u' },
{ index: 1, name: 'CONFIGURATOR_2', key: '-LLnLtLs7PjXSAW0PWCQ' },
];
Desired outcome - Nested arrays of objects
const data = [
{
key: '-LLnLuLt6cn-vBpMWv-u',
name: 'CONFIGURATOR_1',
collections: [
{
key: '-LLnMWy69vACjys0QIGH',
name: 'COLLECTION_1',
options: [
{
key: '-LLnOxg5hsDYR-PcfjBT',
name: 'OPTION_1',
},
{
key: '-LLnP-O6TyHxIpPk9bCU',
name: 'OPTION_2',
},
],
},
{
key: '-LLnMYNyJmhSCPB-8lL1',
name: 'COLLECTION_2',
},
],
},
{ key: '-LLnLtLs7PjXSAW0PWCQ',
name: 'CONFIGURATOR_2',
}]
As usual for this problem, one of the simplest method is to index all object by key with a map M.
then, go through the map M, if the current keyed element has a parent, then add it to the keyed parent in the Map M then map all these elements to an array A. Since all objects in javascript are references, the tree structure would be reconstructed automatically.
The last step would be to filter out all elements in A that have a parent.
const data = [
{ index: 0, parentKey: '-LLnMWy69vACjys0QIGH', type: 'options', name: 'OPTION_1', key: '-LLnOxg5hsDYR-PcfjBT' },
{ index: 1, parentKey: '-LLnMWy69vACjys0QIGH', type: 'options', name: 'OPTION_2', key: '-LLnP-O6TyHxIpPk9bCU' },
{ index: 0, parentKey: '-LLnLuLt6cn-vBpMWv-u', type: 'collections', name: 'COLLECTION_1', key: '-LLnMWy69vACjys0QIGH' },
{ index: 1, parentKey: '-LLnLuLt6cn-vBpMWv-u', type: 'collections', name: 'COLLECTION_2', key: '-LLnMYNyJmhSCPB-8lL1' },
{ index: 0, name: 'CONFIGURATOR_1', key: '-LLnLuLt6cn-vBpMWv-u' },
{ index: 1, name: 'CONFIGURATOR_2', key: '-LLnLtLs7PjXSAW0PWCQ' },
];
const M = data.reduce(function (result, el) {
result[el.key] = el
return result;
}, {});
const A = Object.keys(M).map(key => {
const el = M[key]
if (M[el.parentKey]) {
if (!M[el.parentKey].collections) {
M[el.parentKey].collections = []
}
M[el.parentKey].collections.push(el)
}
return el
}).filter(el => {
return !el.parentKey
})
console.log(JSON.stringify(A, null, '\t'))
I have found my issue using the following function. I am sure there is other ways more efficient ways to do it but it is the cleanest option i have found!
const objectNest = (array, parentKey) => {
const output = [];
array.forEach((object) => {
if (object.parentKey === parentKey) {
const children = objectNest(array, object.key);
if (children.length) { object[children[0].type] = children; }
const { index, parentKey, ...content } = object;
output.push(content);
}
});
return output;
};
I want to return a deconsturcted array so I only get single element in te returned array instead of array.
const data = [
{
title: 'amsterdam',
components: [
{
id: 1,
name: 'yanick',
},
{
id: 2,
name: 'ronald',
},
],
},
{
title: 'rotterdam',
components: [
{
id: 4,
name: 'nicky',
},
{
id: 3,
name: 'casper',
},
],
},
];
const test = data
.map(item => {
console.log(item.components);
return item.components;
}).map(array => {
// how to get comibned components here?
// it can't use ...item.components (deconstructing or something)
});
console.log('test', test);
So I want to use chained map functions to create one array of all elements in item.components. Is this possible? Seems like I can't deconstruct the array of each item.
Array.prototype.reduce seems like the correct method to use in this context.
const test = data.reduce( (result, current) => result.concat(current.components) , []);
console.log('test', test);
Output
test [ { id: 1, name: 'yanick' },
{ id: 2, name: 'ronald' },
{ id: 4, name: 'nicky' },
{ id: 3, name: 'casper' } ]
Get the components with Array.map(), and flatten by spreading into Array.concat():
const data = [{"title":"amsterdam","components":[{"id":1,"name":"yanick"},{"id":2,"name":"ronald"}]},{"title":"rotterdam","components":[{"id":4,"name":"nicky"},{"id":3,"name":"casper"}]}];
const result = [].concat(...data.map(o => o.components));
console.log(result);
To get data combined into single array you can use reduce in combination with concat that will create a single array of results.
const data = [
{
title: 'amsterdam',
components: [
{
id: 1,
name: 'yanick',
},
{
id: 2,
name: 'ronald',
},
],
},
{
title: 'rotterdam',
components: [
{
id: 4,
name: 'nicky',
},
{
id: 3,
name: 'casper',
},
],
},
];
const test = data
.map(item => {
return item.components;
}).reduce((res, item) => {
return res.concat(item);
}, []);
console.log('test', test);