Compare two Arrays and Insert Null Vallues - javascript

I have two arrays:
var array1 = [{id: 1, time: 100}, {id: 2, time: 200}, {id: 3, time: 300}];
var array2 = [{id: 1, time: 100}, {id: 3, time: 300}];
And I would like for array2 to be changed to
var array2 = [{id: 1, time: 100}, null, {id: 3, time: 300}];
The question is how can I compare the two arrays and look at their time and then insert null in the missing locations for each array.
Any help is appreciated!

const arr1 = [{id: 1, time: 100}, {id: 2, time: 200}, {id: 3, time: 300}];
const arr2 = [{id: 1, time: 100}, {id: 3, time: 300}, {id: 3, time: 400}];
const uniqueTimes = [...arr1, ...arr2]
.filter((e, i, a) => a.findIndex(x => x.time === e.time) === i)
const res1 = uniqueTimes.map(e =>
arr1.find(x => x.time === e.time) ?? null
)
const res2 = uniqueTimes.map(e =>
arr2.find(x => x.time === e.time) ?? null
)
console.log(res1)
console.log(res2)

Your example is a little misleading. Your description of the prompt says entries can be missing in both arrays, right? My example has 200 missing in array2, and 400 missing in array1
var array1 = [{ id: 1, time: 100 }, { id: 2, time: 200 }, { id: 3, time: 300 }];
var array2 = [{ id: 1, time: 100 }, { id: 3, time: 300 }, { id: 1, time: 400 }];
// get all possible times, sort them
const allSortedTimes = array1.map(({ time }) => time).concat(array2.map(({ time }) => time)).sort((a, b) => a - b)
// only use uniq times
const allUniqTimes = [...new Set(allSortedTimes)]
// now that we have all the possible times,
// we go over each array and check to see if that time exists
const insertedArray1 = allUniqTimes.map((uniqTime) => {
return array1.find(({ time }) => time === uniqTime) ?? null
})
const insertedArray2 = allUniqTimes.map((uniqTime) => {
return array2.find(({time}) => time === uniqTime) ?? null
})
console.log(insertedArray1)
console.log(insertedArray2)

Here's one way to do it.
var array1 = [{
id: 1,
time: 100
}, {
id: 2,
time: 200
}, {
id: 3,
time: 300
}];
var array2 = [{
id: 1,
time: 100
}, {
id: 3,
time: 300
}];
const fixArray = (a, maxTime) => {
let inc = 100,
start = inc,
tmp = [];
// first make sure we have it in order
//a = a.sort((a, b) => (a.time < b.time) ? -1 : 1)
while (start < maxTime) {
let t = a.filter(el => el.time === start)
if (t.length === 0) tmp.push(null);
else tmp.push(t[0])
start += inc;
}
return tmp
}
array2 = fixArray(array2, 1000);
console.log(array2)

const getKey=(id,time)=>id+"_"+time //Provides unique key based on object values
var array1 = [{id: 1, time: 100}, {id: 2, time: 200}, {id: 3, time: 300}];
var array2 = [{id: 0, time: 5},{id: 1, time: 100},{id: 11, time: 250}, {id: 3, time: 300},{id: 5, time: 500}];
let keysOfArray1=[]//array1 unique keys
let keysOfArray2=[]//array2 unique keys
array1.map(item=>{
keysOfArray1.push(getKey(item.id,item.time)); // collects array1 unique keys
return item
}).concat(array2.map(item=>{//concat array2 values with array1
keysOfArray2.push(getKey(item.id,item.time)) // collects array2 unique keys
return item
})).sort((a,b)=>a.time-b.time || a.id-b.id).reduce((prev,current)=>{ //Sort by time & then Id
let keyName=getKey(current.id,current.time)
if(!prev.includes(keyName)){// To consider all objects only once
array1[prev.length]=keysOfArray1.includes(keyName)?current:null
array2[prev.length]=keysOfArray2.includes(keyName)?current:null
prev.push(keyName)
}
return prev
},[])
console.log(array1);
console.log(array2);

Related

How to check with an array have some values

How to verify with i have only 2 or 3 numbers inside this?
without this ----> if(Array.includes(1) && !Array.includes(3))
const servicesTest: IServices[] = [
{
id: '1',
name: 'Hair',
price: 25,
icon: 'https://cdn-icons-png.flaticon.com/512/7478/7478480.png'
},
{
id: '2',
name: 'Beard',
price: 20,
icon: 'https://cdn-icons-png.flaticon.com/512/7578/7578754.png'
},
{
id: '3',
name: 'Eyebrow',
price: 15,
icon: 'https://cdn-icons-png.flaticon.com/512/2821/2821012.png'
}
]
if the client choose hair + beard this will be 40 not 45.
I´m doing this:
const name = findServices.map(services => services.name)
if (name.includes('Hair') && name.includes('Beard') && !name.includes('Eyebrown')) {
return (
setTotalDay(prevState => prevState + 40),
setTotalMonth(prevState => prevState + 40)
)
}
I would create an array of discounts like this:
const discounts = [{
price: 30,
ids: [1, 2],
}];
Then check if the array has only discounted items like this:
array.length === discount.ids.length && array.every((item) => discount.ids.includes(item.id))
const discounts = [{
price: 30,
ids: [1, 2],
}];
const discounted = [{
id: 1,
name: 'Hair',
price: 20,
},
{
id: 2,
name: 'Beard',
price: 30,
},
];
const fullPrice = [{
id: 1,
name: 'Hair',
price: 20,
},
{
id: 2,
name: 'Beard',
price: 30,
},
{
id: 3,
name: 'Tea',
price: 30,
},
];
console.log("discounted", getTotal(discounted));
console.log("full price", getTotal(fullPrice));
function getTotal(array) {
for (const discount of discounts) {
if (
array.length === discount.ids.length &&
array.every((item) => discount.ids.includes(item.id))
) {
return discount.price;
}
}
return array.reduce((sum, item) => sum + item.price, 0);
}
answering your question before the edit.
Assuming we have this array
const Array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
Let's say we want to check if values 2 and 3 exist.
We store the values in an array let toCheck = [2,3];
We can use function every to loop all the elements of toCheck array against the Array const
Example Follows:
const Array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let toCheck = [1,2];
const allExist = toCheck.every(value => {
return Array.includes(value);
});
Hope it helps.

how get common elements of 2 different arrays and return an object containing the common elements

I have 2 arrays of objects
var array1 = [
{id: 1, name:'fruit', rating:5},
{id: 4, name:'vegetable', rating: 3},
{id: 8, name:'meat', rating:1}
];
var array2 = [
{alimentId: 1, quantity: 2},
{alimentId: 4, quantity: 2},
{alimentId: 8, quantity: 4}
]
and I want to get a new the array1 such that
var array = [
{id: 1, name:'fruit'},
{id: 4, name:'vegetable'},
]
which has only the elements with quantity 2 matching the alimentId with the id.
I'm always getting confused with arrays and objects manipulations.. Please help
I believe the following code will solve your problem:
const func = (arr1, arr2) => {
return arr1.filter(obj => {
const objToCheck = arr2.filter(element => element.alimentId === obj.id);
return objToCheck[0].quantity === 2;
});
};
You also can send the wanted value(2) and the key name(quantity) as params.
var array1 = [
{id: 1, name:'fruit', rating:5},
{id: 4, name:'vegetable', rating: 3},
{id: 8, name:'meat', rating:1}
];
var array2 = [
{alimentId: 1, quantity: 2},
{alimentId: 4, quantity: 2},
{alimentId: 8, quantity: 4}
]
function filter(array1, array2) {
return array1
.filter(it => array2 // filter array1 by array2
.filter(it => it.quantity === 2) // filter your array2 by field quantity = 2
.map(it => it.alimentId) // pull out array of alimentId
.includes(it.id) // check array2.alimentId includes array1.id
)
}
console.log(filter(array1, array2))
use this function
const common_elements = (arr1, arr2, quantity) => {
let res = []
arr1.forEach(el1 => {
arr2.forEach(el2 => {
if(el1.id === el2.alimentId && el2.quantity === quantity) {
res.push(el1)
}
});
});
return res
}
You can do a reduce:
var array3 = array1.reduce((acc ,val ,index) => {
if (val.id=array2[index].alimentId) {
acc =[...acc, {id: val.id, name: val.name}]
}
return acc;
},[]);
var array1 = [
{id: 1, name:'fruit', rating:5},
{id: 4, name:'vegetable', rating: 3},
{id: 8, name:'meat', rating:1}
];
var array2 = [
{alimentId: 1, quantity: 2},
{alimentId: 4, quantity: 2},
{alimentId: 8, quantity: 4}
]
const commonArray = array2.filter(item => item.quantity === 2 && array1.find(el => el.id===item.alimentId));
console.log(commonArray)

Filtering using two array of objects using JavaScript

I have an array as shown:
var arrOne = [{id: 3},{id: 8},{id: 12}];
And another array as shown:
var arrTwo = [
{id: 1, val: 'Adam'},
{id: 3, val: 'Bailey'},
{id: 8, val: 'Cathy'},
{id: 12, val: 'David'},
{id: 15, val: 'Earl'}
];
I want to iterate arrTwo based on arrOne, and get the val values out of arrTwo.
So the result should be:
var result = ['Bailey', 'cathy', 'David'];
Tried concatenating .map with .filter:
arrOne.map(arOne => arrTwo.filter(artwo => {
if(arOne.id === artwo.id) {
return artwo.val
} else {
return false;
}
}));
But it gives me all, and where it is false it adds false there, which I don't want.
Any ideas where I am going wrong will be appreciated.
Editing as per norbitrial's answer:
const arrOne = [{id: 3},{id: 8},{id: 12}];
const arrTwo = [
{id: 1, val: 'Adam'},
{id: 3, val: 'Bailey'},
{id: 8, val: 'Cathy'},
{id: 12, val: 'David'},
{id: 15, val: 'Earl'}
];
const result = arrOne.map(({id}) => arrTwo.find(e => {
const someCond = someConditionaEval();
if(someCond && e.id === id) {
return e;
} else {
return false;
}
}).val); //this breaks
Using .map() and .find() combination:
const arrOne = [{id: 3},{id: 8},{id: 12}];
const arrTwo = [{id: 1, val: 'Adam'}, {id: 3, val: 'Bailey'}, {id: 8, val: 'Cathy'}, {id: 12, val: 'David'}, {id: 15, val: 'Earl'}];
const result = arrOne.map(({id}) => arrTwo.find(e => e.id === id).val);
console.log(result);
I hope this helps!
You can use .filter() method on arrTwo and then using .includes() method get the filtered objects from arrTwo and then finally using .map() get only the val property values from each filtered object like:
var arrOne = [{id: 3},{id: 8},{id: 12}];
var arrTwo = [{id:1,val:"Adam"},{id:3,val:"Bailey"},{id:8,val:"Cathy"},{id:12,val:"David"},{id:15,val:"Earl"}];
var result = arrTwo.filter(a => arrOne.map(o=>o.id).includes(a.id)).map(o=>o.val)
console.log( result )
You could take an object with the values and then map the wanted values.
var arrOne = [{ id: 3 }, { id: 8 }, { id: 12 }],
arrTwo = [{ id: 1, val: 'Adam' }, { id: 3, val: 'Bailey' }, { id: 8, val: 'Cathy' }, { id: 12, val: 'David' }, { id: 15, val: 'Earl' }],
values = arrTwo.reduce((r, { id, val }) => (r[id] = val, r), {}),
result = arrOne.map(({ id }) => values[id]);
console.log(result);
Create a Map of val by id from arrTwo, and then map arrOne, and extract the val from the Map using the id.
Why I prefer creating a Map/dictionary (object) instead of using Array.map() with Array.find()?
Because of the complexity - Array.map() with Array.find(), for example, is O(n * m), while creating a Map and then using Array.map() to get the values is O(n + m). However, if you've got two small arrays, this shouldn't actually hurt actual performance.
const arrOne = [{id: 3},{id: 8},{id: 12}];
const arrTwo = [{id: 1, val: 'Adam'}, {id: 3, val: 'Bailey'}, {id: 8, val: 'Cathy'}, {id: 12, val: 'David'}, {id: 15, val: 'Earl'}];
const valById = new Map(arrTwo.map(({ id, val }) => [id, val]));
const result = arrOne.map(o => valById.get(o.id));
console.log(result);
Build an object from arrTwo to gather val's in one iteration.
use map on arrOne and get val from above object.
const update = (arr1, arr2) => {
const all = Object.fromEntries(arr2.map(({ id, val }) => [id, val]));
return arr1.map(({ id }) => all[id]);
};
var arrOne = [{ id: 3 }, { id: 8 }, { id: 12 }];
var arrTwo = [
{ id: 1, val: "Adam" },
{ id: 3, val: "Bailey" },
{ id: 8, val: "Cathy" },
{ id: 12, val: "David" },
{ id: 15, val: "Earl" }
];
console.log(update(arrOne, arrTwo));

Lodash. How to get aggregate array from array objects

For example, I have an array:
const reference = [{id: 1, value: 10}, {id: 2, value: 10}, {id: 3, value: 10}, {id: 4, value: 5}];
How to get an array values from reference like
const result = [0, 10, 20, 25];
First step always = 0
Second step 0 + 10 = 10
Third step 0 + 10 + 10 = 20
Forth step 0 + 10 + 10 + 5 = 25
You can reduce the array, and add the current value to the last sum:
const reference = [{id: 1, value: 10}, {id: 2, value: 10}, {id: 3, value: 10}, {id: 4, value: 5}];
const result = reference
.reduce((r, o, i) => {
r.push(i === 0 ? 0 : r[r.length - 1] + o.value);
return r;
}, [])
console.log(result);
You could map the values by taking a closure over the sum and take zero for the first element.
const
reference = [{ id: 1, value: 10 }, { id: 2, value: 10 }, { id: 3, value: 10 }, { id: 4, value: 5 }],
result = reference.map((sum => ({ value }, i) => sum += i && value)(0));
console.log(result);
The way I would do this would be by using the Array.reduce method as follows :
let result = [0]
reference.reduce((acc, cur) => {
result.push(Object.values(cur)[1]+result[result.length-1])
})
Hope it helps

How to create array of array by grouping ids

I have an array:
let array = [{id: 1, name:'a'}, {id: 2, name: 'b'},{id: 1, name:'c'}];
I want an array like
arr2 = [[{id: 1, name:'a'}, {id: 1, name:'c'}], [{id: 2, name: 'b'}]]
I tried this but I cant find which array to add to:
$scope.journalsArray = response.data.body.Data;
$scope.newArray = [];
let idsArray = [];
for (let i = 0; i < $scope.journalsArray.length; i++) {
if(idsArray.indexOf($scope.journalsArray[i].journal_id) != -1){
$scope.newArray.push($scope.journalsArray[i]);
}else{
$scope.idsArray.push($scope.journalsArray[i].journal_id);
}
}
Array.reduce over your original array.
If a group exists that has an item with the same id, push into it.
Otherwise create the group.
let array = [{id: 1, name:'a'}, {id: 2, name: 'b'},{id: 1, name:'c'}]
let result = array.reduce((acc, item) => {
const group = acc.find(group => group.find(inner => inner.id === item.id))
if (group)
group.push(item)
else
acc.push([item])
return acc
}, [])
console.log(result)
Using reduce(), find() and filter() methods we can achieve this
let array = [
{id: 1, name:'a'},
{id: 2, name: 'b'},
{id: 1, name:'c'}
];
const results = arr => {
return arr.reduce((result, item ) => {
if (!result.find(obj => obj[0].id === item.id)) {
result.push(array.filter(val => val.id == item.id))
}
return result;
}, [])
}
console.log(results(array));
// ​​​​​[ [ { id: 1, name: 'a' }, { id: 1, name: 'c' } ], [ { id: 2, name: 'b' } ] ]​​
You could take a Map and collect the objects in the same group. Then get the values of each group as result.
var array = [{ id: 1, name:'a' }, { id: 2, name: 'b' },{ id: 1, name:'c' }],
result = Array.from(
array
.reduce((m, o) => m.set(o.id, [...(m.get(o.id) || []), o]), new Map)
.values()
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Using Array#reduce, Map, destructuring and Array#concat.
const data = [{id: 1, name:'a'}, {id: 2, name: 'b'},{id: 1, name:'c'}];
const res = data.reduce((a,{id,name})=>{
return a.set(id, [{id,name}].concat(a.get(id)||[]));
}, new Map()).values();
console.log([...res]);
let array = [{id: 1, name:'a'}, {id: 2, name: 'b'},{id: 1, name:'c'}]
let result = array.reduce((acc, item) => {
const group = acc.find(group => group.find(inner => inner.id === item.id))
if (group)
group.push(item)
else
acc.push([item])
return acc
}, [])
console.log(result)
let array = [{id: 1, name:'a'}, {id: 2, name: 'b'},{id: 1, name:'c'}]
let result = array.reduce((acc, item) => {
const group = acc.find(group => group.find(inner => inner.id === item.id))
if (group)
group.push(item)
else
acc.push([item])
return acc
}, [])
console.log(result)

Categories