compare two array of object - javascript

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

Related

Problem with using for-in/of when returning an object in a function

I just got the result "[object Object]'s score is 0" printed on the terminal.
The result 27 was all fine until I separated the function into a return object.
How do I get 27 if I have to return an object?
How do I get "alex" printed on the console.log instead of [object Object]?
const alex = {
first: [1, 2, 9, 8],
second: [3],
third: [0, 0, 0, 1, 3]
};
const gordon = {
first: [3],
second: [2, 2, 4, 5, 6, 6, 7, 8]
}
function createPlayer(object) {
let score = 0;
return {
add: function() {
for (const key in object) {
for (const item in object[key]) {
score += object[key][item]
}
}
},
result: function() {
return `${object}\'s score is ${score}`
}
}
}
createPlayer(alex).add()
console.log(createPlayer(alex).result())
const alex = {
first: [1, 2, 9, 8],
second: [3],
third: [0, 0, 0, 1, 3]
};
const gordon = {
first: [3],
second: [2, 2, 4, 5, 6, 6, 7, 8]
}
function createPlayer(object, name) {
let score = 0;
return {
add: function() {
for (const key in object) {
for (const item in object[key]) {
score += object[key][item]
}
}
return this; // <<<<<
},
result: function() {
return `${name}\'s score is ${score}`
}
}
}
console.log(createPlayer(alex, 'Alex').add().result())
You would not show alex for an object named alex
You might mean this
const alex = {
Name: "Alex",
first: [1, 2, 9, 8],
second: [3],
third: [0, 0, 0, 1, 3]
};
const gordon = {
Name: "Gordon",
first: [3],
second: [2, 2, 4, 5, 6, 6, 7, 8]
}
function createPlayer(object) {
let score = 0;
return {
add: function() {
for (const key in object) {
if (key!=="Name") {
for (const item in object[key]) {
score += object[key][item]
}
}
}
},
result: function() {
return `${object.Name}\'s score is ${score}`
}
}
}
const player1 = createPlayer(alex)
player1.add()
console.log(player1.result())

How to find if a specific key is true in Array of objects

I have this array and I want to to get a boolean(true) if there is a 'three' that is equal to 9
myArr = [
{
apple: 6,
basket: [
{
one: 1,
two: 2,
three: 3
},
{
one: 4,
two: 5,
three: 6
}
]
},
{
apple: 9,
basket: [
{
one: 1,
two: 2,
three: 3
},
{
one: 4,
two: 5,
three: 9
}
]
}
]
What I tried:
enter code here
this.myArr.forEach( data => {
if(data.basket.filter(cur => cur.one === 0 || cur.three === 9)) {
console.log('true')
}
})
This always logs true for some reason I don't know why.
.filter will always return an array of elements which pass the test, and arrays are truthy. Even if no elements pass the test, the array will still be truthy:
const arr = [1, 2, 3].filter(() => false);
if (arr) {
console.log('truthy');
}
Use .some instead, to see if there is at least one element which passes the test:
const myArr = [{
apple: 6,
basket: [{
one: 1,
two: 2,
three: 3
}, {
one: 4,
two: 5,
three: 6
}]
}, {
apple: 9,
basket: [{
one: 1,
two: 2,
three: 3
}, {
one: 4,
two: 5,
three: 9
}]
}]
myArr.forEach(data => {
if (data.basket.some(cur => cur.one === 0 || cur.three === 9)) {
console.log('true');
}
});
filter returns to array and use find which will return matched item or null when no match.
In you code, Just change from filter to find will work fine.
const myArr = [
{
apple: 6,
basket: [
{ one: 1, two: 2, three: 3 },
{ one: 4, two: 5, three: 6 }
]
},
{
apple: 9,
basket: [
{ one: 1, two: 2, three: 3 },
{ one: 4, two: 5, three: 9 }
]
}
];
const items = myArr.map(data =>
data.basket.find(cur => cur.one === 0 || cur.three === 9) ? "true" : "false"
);
console.log(items);

Issue with concat of arrays

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)

Group array of objects depending on values

I have an array of objects
[
{ values: [2, 7, 1] },
{ values: [1, 2, 7] },
{ values: [7, 1, 2] },
{ values: [3, 4, 5] },
{ values: [2, 1, 8] },
{ values: [2, 1, 8] },
]
I want to group these objects together with the other object with same values. So this array of objects should be grouped into 3 groups since the first 3 objects have the same values, the next object is alone and the last 2 objects have the same values.
As seen in the example, the values can have different orders, but should still be considered the same.
I am thinking about for each element to loop through the remaining elements and see if they are alike, but it will result in O(n^2).
I guess I should remove elements from the array that has already been grouped.
So how could I, efficiently, group it as
[[first, second, third],[fourth],[fifth,sixth]]
Something like this?
var data = [
{ values: [2, 7, 1] },
{ values: [1, 2, 7] },
{ values: [7, 1, 2] },
{ values: [3, 4, 5] },
{ values: [2, 1, 8] },
{ values: [2, 1, 8] },
];
var hash = {};
for(var obj of data) {
var key = obj.values.sort().join("-");
if (!hash[key]) hash[key] = [];
hash[key].push(obj);
}
var result = [];
for(var k in hash) result.push(hash[k])
console.log(result)
Or js6 variant:
var data = [
{ values: [2, 7, 1] },
{ values: [1, 2, 7] },
{ values: [7, 1, 2] },
{ values: [3, 4, 5] },
{ values: [2, 1, 8] },
{ values: [2, 1, 8] },
];
var hash = data.reduce((hash, obj) => {
const key = obj.values.sort().join("-");
if (!hash[key]) hash[key] = [];
hash[key].push(obj);
return hash;
}, [])
var result = Object.keys(hash).map(k => hash[k])
console.log(result)
You can do this with forEach() loop and sort()
var arr = [
{ values: [2, 7, 1] },
{ values: [1, 2, 7] },
{ values: [7, 1, 2] },
{ values: [3, 4, 5] },
{ values: [2, 1, 8] },
{ values: [2, 1, 8] },
];
var result = [];
arr.forEach(function(e) {
var s = [].concat(e.values).sort().join('|');
if (!this[s]) {
this[s] = [e.values];
result.push(this[s]);
} else {
this[s].push(e.values)
}
})
console.log(result)

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