Issue with concat of arrays - javascript

I have the next code:
let arr = [{
id: 1,
name: 'test',
cars: [{
nr: [5, 4]
},
{
nr: [2]
},
{
nr: [1]
},
{
nr: [5, 4]
}
],
},
{
id: 2,
name: 'test2',
cars: [{
nr: [5, 4]
},
{
nr: [2]
},
{
nr: [8]
},
{
nr: [5, 4]
}
],
}
]
const res = arr.reduce(i => i.cars).map(i => i.nr.map(i => [].concat(i)))
console.log(res)
As a result i expect an array with concatenates values from nr. For example as a result i should get 2 arrays. One for id1 and another for id2. First array should look like this: [5,4,2,1,5,4], and second should implement the same logic.
For this i make:
const res = arr.reduce(i => i.cars).map(i=> i.nr.map(i =>[].concat(i))), but it does not work. Ho to get expected result?

You want to map first over all elements and get the array of car ids through a reduce function.
const res = arr.map(({ cars }) => cars.reduce((acc, { nr }) => [...acc, ...nr], [])));
res; // => [ [ 5, 4, 2, 1, 5, 4 ], [ 5, 4, 2, 8, 5, 4 ] ]
Let me know if that's clear enough or if you have any questions!

You can use map which will return a new array along with reduce on cars. Inside reduce call back you can concat the current nr. SInce concat returns a new array so reassigning the value to accumulator
Edit: Use another reduce function to add the values
let arr = [{
id: 1,
name: 'test',
cars: [{
nr: [5, 4]
},
{
nr: [2]
},
{
nr: [1]
},
{
nr: [5, 4]
}
],
},
{
id: 2,
name: 'test2',
cars: [{
nr: [5, 4]
},
{
nr: [2]
},
{
nr: [8]
},
{
nr: [5, 4]
}
],
}
]
const res = arr.map((item) => {
return item.cars.reduce((acc, curr) => {
acc = acc.concat(curr.nr)
return acc;
}, []).reduce((acc, curr) => {
return acc + curr;
}, 0);
});
console.log(res)

Well, It was not clear for me what you are looking for. However, here is a sample code to collect nr ids for each set separately.
let arr = [{
id: 1,
name: 'test',
cars: [{
nr: [5, 4]
},
{
nr: [2]
},
{
nr: [1]
},
{
nr: [5, 4]
}
],
},
{
id: 2,
name: 'test2',
cars: [{
nr: [5, 4]
},
{
nr: [2]
},
{
nr: [8]
},
{
nr: [5, 4]
}
],
}
]
const res = arr
.map(i => i.cars)
.map(i => i
.map(i => i.nr)
.reduce((result,i)=>result.concat(i),[]));
console.log(res)
If you want to remove duplicated items:
let arr = [{
id: 1,
name: 'test',
cars: [{
nr: [5, 4]
},
{
nr: [2]
},
{
nr: [1]
},
{
nr: [5, 4]
}
],
},
{
id: 2,
name: 'test2',
cars: [{
nr: [5, 4]
},
{
nr: [2]
},
{
nr: [8]
},
{
nr: [5, 4]
}
],
}
]
const res = arr
.map(i => i.cars)
.map(i => i
.map(i => i.nr)
.reduce(function(result,i){
i.map(item=>{
if(result.indexOf(item)<0){
result.push(item);
}
});
return result;
},[]));
console.log(res)

Related

Convert Nested object into custom array of objects: Javascript

I am having array of objects that look like this
const test = {
a: { name: "A", selected: [1, 2, 3], display: [1, 2, 3] },
b: { name: "B", selected: [4, 5, 6], display: [4, 5, 6] },
c: { name: "C", selected: [7, 8, 9], display: [7, 8, 9] },
d: { name: "D", selected: [], display: [] }
};
I want the above to be converted as below
const output = [
{ field: "A", selectedValues: [1, 2, 3] },
{ field: "B", selectedValues: [4, 5, 6] },
{ field: "C", selectedValues: [7, 8, 9] }
];
Basically key in the input object to be made as field in the final object of that array and selected in input object should be made as selectedValues in the final object. Note only the object that has some entries selected should be put into final arrray
Also when all the objects in the input object have selected as empty then just return empty array else return the above output.
Code that I tried
const result = Object.entries(test).map(([name, v]) => ({
field: name,
selectedValues: v
}));
console.log(result);
Because you want
selected in input object should be made as selectedValues in the final object.
you should navigate to the .selected property (the subarray) while mapping, instead of referencing the whole object. Afterwards, filter by whether that array has any values in it.
const test = {
a: { name: "A", selected: [1, 2, 3], display: [1, 2, 3] },
b: { name: "B", selected: [4, 5, 6], display: [4, 5, 6] },
c: { name: "C", selected: [7, 8, 9], display: [7, 8, 9] },
d: { name: "D", selected: [], display: [] }
};
const result = Object.entries(test)
.map(([name, obj]) => ({
field: name,
selectedValues: obj.selected
}))
.filter(({ selectedValues }) => selectedValues.length);
console.log(result);

How can I replace array item with matched object keys?

Let's say I have an array of id's
const ids = [[1, 2, 3], [2, 3], [3]]
And have array with objects that have name for each id
const obj = [
{ id: 1, name: "One" },
{ id: 2, name: "Two" },
{ id: 3, name: "Three" },
];
What is the most proper way to get ids = [["One", "Two", "Three"], ["Two", "Three"], ["Three"]], I'm worrying that nested mapping could cause performance issues.
Use a combination of map and find. There may be a more performant way of doing it, but I'd suggest worrying about that only if you run into performance issues :-
const ids = [[1, 2, 3], [2, 3], [3]];
const obj = [
{ id: 1, name: "One" },
{ id: 2, name: "Two" },
{ id: 3, name: "Three" },
];
const mapped = ids.map(arr => arr.map(id => obj.find(obj => obj.id === id).name));
const obj = [
{ id: 1, name: "One" },
{ id: 2, name: "Two" },
{ id: 3, name: "Three" },
];
const ids = [[1, 2, 3], [2, 3], [3]] ;
// dedicated object to keep association between id and names
let names = {} ;
obj.forEach( o => {
names[ o.id ] = o.name ;
} ) ;
// map each sub array content to their real name
for( let i = 0; i <= ids.length-1; i++){
ids[i] = ids[i].map( id => names[id] ) ;
}
console.log( ids ) ;
=>
[ [ 'One', 'Two', 'Three' ], [ 'Two', 'Three' ], [ 'Three' ] ]

compare two array of object

I have an array of objects in JavaScript and would like to filter it, if there is two events that are equel so their days concat and if there is duplicate value in days array remove it.
here is my array:
[ { event: 'approvalDate', days: [ 1, 2, 3, 4, 5] },
{ event: 'appointDate', days: [ 1 ] },
{ event: 'approvalDate', days: [ 120, 14, 9, 4, 1, 2 ] } ]
I want the result like this
[ { event: 'approvalDate', days: [ 1, 2, 3, 4, 5,120, 14, 9] },
{ event: 'appointDate', days: [ 1 ] },
]
const items = [
{ event: 'approvalDate', days: [1, 2, 3, 4, 5] },
{ event: 'appointDate', days: [1] },
{ event: 'approvalDate', days: [120, 14, 9, 4, 1, 2] },
];
const result = [];
items.forEach((item) => {
if (!result.find((e) => e.event === item.event)) {
result.push(item);
} else {
const index = result.findIndex((e) => e.event === item.event);
result[index].days = [...new Set([...result[index].days, ...item.days])];
}
});
You could just concat everything then deduplicate. You need to sort the array.
function go(){
let out=deduplicate([1,2,2,2,2,3,4,4,4,4,4,5,5,5,6,7,8,9,10]);
console.log(out);
}
function deduplicate(array){
array=array.sort(function(a,b){return a-b;});
let output=[array[0]];
for (let i=1;i<array.length;i++){
if(array[i] != output[output.length-1])output.push(array[i]);
}
return output;
}

How to filter and get array by id?

const id = [1, 4, 10]
const data =[{id: 1, name: Banana}, {id: 2, name: Mango}, {id: 3, name: Chili}, {id: 4, name: WaterMelon}, {id: 10, name: WaterMelon}]
I tried filter It's showing me empty value. I want to remove matched by id in an array.
Use filter() with includes():
const result = data.filter(({id}) => !ids.includes(id));
Full snippet:
const ids = [1, 4, 10];
const data = [{
id: 1,
name: 'Banana'
}, {
id: 2,
name: 'Mango'
}, {
id: 3,
name: 'Chili'
}, {
id: 4,
name: 'WaterMelon'
}, {
id: 10,
name: 'WaterMelon'
}];
const result = data.filter(({id}) => !ids.includes(id));
console.log(result);
If you want to filter out matched ID, try this code:
const result = data.filter(({id}) => ids.indexOf(id) < 0);
const ids = [1, 4, 10]
const data =[{id: 1, name: 'Banana'}, {id: 2, name: 'Mango'}, {id: 3, name: 'Chili'}, {id: 4, name: 'WaterMelon'}, {id: 10, name: 'WaterMelon'}];
const result = data.filter(({id}) => ids.indexOf(id) < 0);
console.log(result);
using filter it will select the ids of data,
and your object name type data should be string or maybe you want it as a variable so you will not get error.
data.filter((object) => !id.includes(object.id))
const result=data.filter((value)=>!id.includes(value.id))

Concat multi-dimensional array into one-dimensional array

I have an array with objects
const nodes = [ { children: [1, 2, 3] }, { children: [1, 2, 3] } ];
I want a new array [ 1, 2, 3, 1, 2, 3 ].
I have tried
nodes.map(node => node.children);
but it gives me [ [ 1, 2, 3 ], [ 1, 2, 3 ] ].
I have tried
[].concat(nodes.map(node => node.children));
but it doesn't work since it is just concatenating [] with [ [ 1, 2, 3 ], [ 1, 2, 3 ] ] which is just [ [ 1, 2, 3 ], [ 1, 2, 3 ] ].
You could use Array#reduce
const nodes = [ { children: [1, 2, 3] }, { children: [1, 2, 3] } ],
result = nodes.reduce((r, node) => r.concat(node.children), []);
console.log(result);
console.log([... new Set(result)]); // for unique values
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can do this with Array#reduce
const nodes = [ { children: [1, 2, 3] }, { children: [1, 2, 3] } ];
var result = nodes.reduce(function(r, o) {
r = r.concat(o.children);
return r;
}, []);
console.log(result)
Another way to do this using Array#forEach:
const nodes = [ { children: [1, 2, 3] }, { children: [1, 2, 3] } ]
final = []
nodes.forEach(x => final = final.concat(x.children))
console.log(final)
Another shorter way is (a little modification to what OP was trying to do):
const nodes = [ { children: [1, 2, 3] }, { children: [1, 2, 3] } ];
var result = [].concat.apply([], nodes.map(x => x.children))
console.log(result);

Categories

Resources