Combine Promises Arrays, in Only One JavaScript - javascript

I am using some promises to get information, but in this case I have a principal array, my idea is:
For loop to each company id to get payment
For loop to each payment array id to get employers
Show in one array the results
MY CODE
var data = [
{
id: 1,
company: 'A'
},
{
id: 2,
company: 'B'
},
{
id: 3,
company: 'C'
}
]
var p1 = [];
for(var i =0; i < data.length; i++){
p1.push(global.get_payments(data, i));
}
Promise.all(p1)
.then(response_p1 => {
//I added the response in same structure see response_p1
for(var i =0; i < response_p1.length; i++){
var employers = [];
for(var x =0; x < response_p1[i].payment.length; x++){
employers.push(global.get_employers(response_p1[i].payment, x));
}
Promise.all(employers)
.then(response_employers => {
//I added the response into payment array
//HOW CAN I COMBINE IN ONLY ONE ARRAY?
}).catch(err => {
console.log(err)
})
}
}).catch(err => {
console.log(err)
})
response_p1 = [
{
id: 1,
company: A',
payment: [
{id: 4}
]
},
{
id: 2,
company: 'B',
payment: [
{id: 5}
]
},
{
id: 3,
company: 'C',
payment: [
{id: 6}
]
}
]
response_employers = [
{
id: 4,
employer_list: [
{id: 1, name: 'Carles'},
{id: 2, name: 'Max'}
]
}
]
[
{
id: 5,
employer_list: [
{id: 3, name: 'Dania'},
{id: 4, name: 'Luis'}
]
}
]
[
{
id: 6,
employer_list: [
{id: 5, name: 'Lenny'},
{id: 6, name: 'Hommer'}
]
}
]
RESULT EXPECTED [
{
id: 4,
employer_list: [
{id: 1, name: 'Carles'},
{id: 2, name: 'Max'}
]
},
{
id: 5,
employer_list: [
{id: 3, name: 'Dania'},
{id: 4, name: 'Luis'}
]
},
{
id: 6,
employer_list: [
{id: 5, name: 'Lenny'},
{id: 6, name: 'Hommer'}
]
}
]
my problem is that I am getting 3 array and I want that response_employers should be in only one array, How can I solve that

Related

Removing passed array of objects from an array of objects [duplicate]

I want to filter array of objects by another array of objects.
I have 2 array of objects like this:
const array = [
{ id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } },
{ id: 2, name: 'a2', sub: null },
{ id: 3, name: 'a3', sub: { id: 8, name: 'a3 sub' } },
{ id: 4, name: 'a4', sub: null },
{ id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } },
];
const anotherArray = [
{ id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } },
{ id: 2, name: 'a2', sub: null },
{ id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } },
];
and I want filter array by anotherArray and return items that is not exist in anotherArray and have sub.
So my desired output is:
[ { id: 3, name: 'a3', sub: { id: 8, name: 'a3 sub' } ]
Note: I've done this with for loop but it work too slow. I want to do this with using Arrays filter method
Code I have with for loop:
for (let i = 0; i < array.length; i += 1) {
let exist = false;
const item = array[i];
for (let j = 0; j < anotherArray.length; j += 1) {
const anotherItem = anotherArray[j];
if (item.id === anotherItem.id) {
exist = true;
}
}
if (item.sub && !exist) {
this.newArray.push({
text: `${item.sub.name} / ${item.name}`,
value: item.id,
});
}
}
Like Felix mentioned, Array#filter won't work faster than native for loop, however if you really want it as functional way, here's one possible solution:
const array = [
{ id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } },
{ id: 2, name: 'a2', sub: null },
{ id: 3, name: 'a3', sub: { id: 8, name: 'a3 sub' } },
{ id: 4, name: 'a4', sub: null },
{ id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } },
];
const anotherArray = [
{ id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } },
{ id: 2, name: 'a2', sub: null },
{ id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } },
];
const r = array.filter((elem) => !anotherArray.find(({ id }) => elem.id === id) && elem.sub);
console.log(r);
You can use Array.filter and then Array.some since the later would return boolean instead of the element like Array.find would:
const a1 = [ { id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } }, { id: 2, name: 'a2', sub: null }, { id: 3, name: 'a3', sub: { id: 8, name: 'a3 sub' } }, { id: 4, name: 'a4', sub: null }, { id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } }, ];
const a2 = [ { id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } }, { id: 2, name: 'a2', sub: null }, { id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } }, ];
const result = a1.filter(({id, sub}) => !a2.some(x => x.id == id) && sub)
console.log(result)
You could use JSON.stringify to compare the two objects. It would be better to write a function that compares all properties on the objects recursively.
const array = [
{ id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } },
{ id: 2, name: 'a2', sub: null },
{ id: 3, name: 'a3', sub: { id: 8, name: 'a3 sub' } },
{ id: 4, name: 'a4', sub: null },
{ id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } },
];
const anotherArray = [
{ id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } },
{ id: 2, name: 'a2', sub: null },
{ id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } },
];
const notIn = (array1, array2) => array1.filter(item1 => {
const item1Str = JSON.stringify(item1);
return !array2.find(item2 => item1Str === JSON.stringify(item2))
}
);
console.log(notIn(array, anotherArray));
Ok, let's solve this step by step.
To simplify the process let's suppose that two elements can be considered equals if they both have the same id.
The first approach that I would use is to iterate the first array and, for each element, iterate the second one to check the conditions that you've defined above.
const A = [ /* ... */]
const B = [ /* ... */]
A.filter(el => {
let existsInB = !!B.find(e => {
return e.id === el.id
}
return existsInB && !!B.sub
})
If we are sure that the elements in A and in B are really the same when they have the same ID, we could skip all the A elements without the sub property to perform it up a little bit
A.filter(el => {
if (!el.sub) return false
let existsInB = !!B.find(e => {
return e.id === el.id
}
return existsInB
})
Now, if our arrays are bigger than that, it means that we are wasting a lot of time looking for the element into B.
Usually, in these cases, I transform the array where I look for into a map, like this
var BMap = {}
B.forEach(el => {
BMap[el.id] = el
})
A.filter(el => {
if (!el.sub) return false
return !!BMap[el.id]
})
In this way you "waste" a little bit of time to create your map at the beginning, but then you can find your elements quicker.
From here there could be even more optimizations but I think this is enought for this question
OPTIMIZED VERSION
const array = [{
id: 1,
name: "a1",
sub: {
id: 6,
name: "a1 sub"
}
},
{
id: 2,
name: "a2",
sub: null
},
{
id: 3,
name: "a3",
sub: {
id: 8,
name: "a3 sub"
}
},
{
id: 4,
name: "a4",
sub: null
},
{
id: 5,
name: "a5",
sub: {
id: 10,
name: "a5 sub"
}
},
];
const anotherArray = [{
id: 1,
name: "a1",
sub: {
id: 6,
name: "a1 sub"
}
},
{
id: 2,
name: "a2",
sub: null
},
{
id: 5,
name: "a5",
sub: {
id: 10,
name: "a5 sub"
}
},
];
const dict = anotherArray.reduce((acc, curr) => {
const { id } = curr;
acc[id] = curr;
return acc;
}, {});
const result = array.filter((obj) => {
const search = dict[obj.id];
if (!search && obj.sub) return true;
return false;
});
console.log(result);

Counting number of occurances of in primary array A that are in array B

I want to get the count of Items in array A that are in B and return an array C that contains the count elements.
array A is:
arrA = [{id:1,name:"Nairobi"},{id:2,name:"New Delhi"},{id:3,name:"Singapore"},{id:4,name:"London"}]
array B is:
arrB = [{id:1,id_fk:1,name:"Steve"},{id:2,id_fk:1,name:"John"},{id:3,id_fk:2,name:"Stella"},{id:4,id_fk:3,name:"Kemi"},{id:5,id_fk:3,name:"Kelly"},{id:6,id_fk:4,name:"James"},{id:7,id_fk:4,name:"Marley"},{id:8,id_fk:4,name:"Oliver"}]
Using id_fk in array B as a "foreign key" for id in array A, the expected output is
[2,1,2,3]
My implementation code is
for (let arrayA of arrA){
let count = arrB.filter(a =>
{return a.id_fk === arrayA.id}).length;
}
You could take a Map and get the id as keys in the wanted order and reduce the second array for counting items with id_fk. As result take an array of the values of the map.
This approach uses a single loop for getting the id as keys and another loop for counting.
var arrA = [{ id: 1, name: "Nairobi" }, { id: 2, name: "New Delhi" }, { id: 3, name: "Singapore" }, { id: 4, name: "London" }],
arrB = [{ id: 1, id_fk: 1, name: "Steve" }, { id: 2, id_fk: 1, name: "John" }, { id: 3, id_fk: 2, name: "Stella" }, { id: 4, id_fk: 3, name: "Kemi" }, { id: 5, id_fk: 3, name: "Kelly" }, { id: 6, id_fk: 4, name: "James" }, { id: 7, id_fk: 4, name: "Marley" }, { id: 8, id_fk: 4, name: "Oliver" }],
result = Array.from(arrB
.reduce(
(m, { id_fk }) => m.set(id_fk, m.get(id_fk) + 1),
new Map(arrA.map(({ id }) => [id, 0]))
)
.values()
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
A result with a hash table and new objects with a count property.
var arrA = [{ id: 1, name: "Nairobi" }, { id: 2, name: "New Delhi" }, { id: 3, name: "Singapore" }, { id: 4, name: "London" }],
arrB = [{ id: 1, id_fk: 1, name: "Steve" }, { id: 2, id_fk: 1, name: "John" }, { id: 3, id_fk: 2, name: "Stella" }, { id: 4, id_fk: 3, name: "Kemi" }, { id: 5, id_fk: 3, name: "Kelly" }, { id: 6, id_fk: 4, name: "James" }, { id: 7, id_fk: 4, name: "Marley" }, { id: 8, id_fk: 4, name: "Oliver" }],
hash = {},
result = arrA.map(o => Object.assign(hash[o.id] = {}, o, { count: 0 }));
arrB.forEach(({ id_fk }) => hash[id_fk].count++);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I would do it like this. https://jsfiddle.net/6egs7uLy/
let counts = [];
arrA.forEach((item, index) => {
let count = 0;
arrB.forEach((item2, index) => {
if(item['id'] === item2['id_fk']) {
count++;
}
})
counts.push(count);
count = 0;
})

How to find third values comparing two values in javascript?

Here I have two arrays array1 and array2 I want to find ids from array1 which array1's names matched with array2 values how to find ids in javascript ?
array1:
[ {id: 1, name: "Hindi"}
{id: 2, name: "English"}
{id: 3, name: "French"}
{id: 4, name: "Russian"}
{id: 5, name: "Urdu"}
{id: 6, name: "Japanese"}
]
array2:
["Hindi", "Russian", "Urdu"]
I tried this code
console.log(array1.find(x => x.name === array2).id;
You can use filter() to get objects whose names are in the array.Then use map() to convert array of values to array of ids.
In your code you are comparing the string with array x.name === array2. You should use includes()
let arr = [ {id: 1, name: "Hindi"}, {id: 2, name: "English"}, {id: 3, name: "French"}, {id: 4, name: "Russian"}, {id: 5, name: "Urdu"}, {id: 6, name: "Japanese"} ]
let lang = ["Hindi", "Russian", "Urdu"];
let res = arr.filter(x => lang.includes(x.name)).map(x => x.id);
console.log(res)
You should use filter method in combination with map and destructuring
let arr1 = [ {id: 1, name: "Hindi"}, {id: 2, name: "English"}, {id: 3, name: "French"}, {id: 4, name: "Russian"}, {id: 5, name: "Urdu"}, {id: 6, name: "Japanese"} ], arr2 = ["Hindi", "Russian", "Urdu"];
console.log(arr1.filter(({name}) => arr2.includes(name)).map(({id}) => id));
Try this:
var a = [{
id: 1,
name: "Hindi"
}, {
id: 2,
name: "English"
}, {
id: 3,
name: "French"
}, {
id: 4,
name: "Russian"
}, {
id: 5,
name: "Urdu"
}, {
id: 6,
name: "Japanese"
}]
var b = ["Hindi", "Russian", "Urdu"];
var c = a.filter(function(i){
return b.indexOf(i.name)>-1;
});
console.log(c); // New Array with filtered values
This will work too :)
var a1 = [{
id: 1,
name: "Hindi"
}, {
id: 2,
name: "English"
}, {
id: 3,
name: "French"
}, {
id: 4,
name: "Russian"
}, {
id: 5,
name: "Urdu"
}, {
id: 6,
name: "Japanese"
}]
var a2 = ["Hindi", "Russian", "Urdu"];
var filter = a1.filter(function(i) {
return a2.indexOf(i.name) > -1;
}).map(function(obj) {
return obj.id;
});;
console.log(filter);

Find if object's array has elements from another array using Lodash

There is an array of products, each product has structure like this:
{
id: 1,
name: "product 1",
materials: [
{
id: 1,
name: "material 1"
},
{
id: 2,
name: "material 2"
},
{
id: 3,
name: "material 3"
}
]
}
Each product has an array with different quantity of materials.
Also there is an array of material IDs, for example [1, 4, 7, 2, 5].
How can I filter the array of products to leave only products, where materials has IDs which are in the array of materials IDs?
try
products.filter(p=> p.materials.some(m=> materialsIds.includes(m.id)));
let materialsIds = [1, 4, 7, 2, 5];
let products = [
{ id: 1, name: "product 1", materials: [{id: 1,name: "material 1"},{id: 2,name: "material 2"},{id: 3, name: "material 3"}]},
{ id: 2, name: "product 2", materials: [{id: 2, name: "material 2"}]},
{ id: 3, name: "product 3", materials: [{id: 3, name: "material 3"}]},
]
let r = products.filter(p=> p.materials.some(m=> materialsIds.includes(m.id)));
console.log('Filtered products ids', r.map(p=>p.id));
console.log('Filtered products', JSON.stringify(r));
You can do this :
import {intersection} from 'lodash'
const products = [...]
const materialIds = [1,4,7,2,5]
// some function use es5+
const targetProducts = products.filter(p => intersection(p.materials.map(m => m.id), materialIds).length)
// use lodash only import {filter, map, intersection} from 'lodash'
const targetProducts = filter(products, p => intersection(map(p.materials, 'id'), materialIds).length)
You can do that using filter() some()and includes()
Use filter() on the main array of products
Then use some() on the materials of object.
Check if mats(material ids) includes id of material
let arr = [{ id: 1, name: "product 1", materials: [ { id: 1, name: "material 1" }, { id: 2, name: "material 2" }, { id: 3, name: "material 3" } ] },{ id: 2, name: "product 2", materials: [ { id: 11, name: "material 11" }, { id: 22, name: "material 22" }, { id: 33, name: "material 33" } ] }
]
let mats = [1,5,6];
let res = arr.filter(x => x.materials.some(z=> mats.includes(z.id)));
console.log(res)
const products = [
{
id: 1,
name: 'product 1',
materials: [
{
id: 1,
name: 'material 1'
},
{
id: 7,
name: 'material 7'
},
{
id: 5,
name: 'material 5'
}
]
},
{
id: 2,
name: 'product 2',
materials: [
{
id: 1,
name: 'material 1'
},
{
id: 2,
name: 'material 2'
},
{
id: 3,
name: 'material 3'
}
]
}
];
const materials = [3, 4];
console.log(
products.filter(product => {
for (let i = 0; i < product.materials.length; i++) {
if (materials.includes(product.materials[i].id)) return true;
}
})
);
I would do it like this:
products.filter(product => {
for (let i = 0; i < product.materials.length; i++) {
if (materials.includes(product.materials[i].id)) return true;
}
})

filter array of objects by another array of objects

I want to filter array of objects by another array of objects.
I have 2 array of objects like this:
const array = [
{ id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } },
{ id: 2, name: 'a2', sub: null },
{ id: 3, name: 'a3', sub: { id: 8, name: 'a3 sub' } },
{ id: 4, name: 'a4', sub: null },
{ id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } },
];
const anotherArray = [
{ id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } },
{ id: 2, name: 'a2', sub: null },
{ id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } },
];
and I want filter array by anotherArray and return items that is not exist in anotherArray and have sub.
So my desired output is:
[ { id: 3, name: 'a3', sub: { id: 8, name: 'a3 sub' } ]
Note: I've done this with for loop but it work too slow. I want to do this with using Arrays filter method
Code I have with for loop:
for (let i = 0; i < array.length; i += 1) {
let exist = false;
const item = array[i];
for (let j = 0; j < anotherArray.length; j += 1) {
const anotherItem = anotherArray[j];
if (item.id === anotherItem.id) {
exist = true;
}
}
if (item.sub && !exist) {
this.newArray.push({
text: `${item.sub.name} / ${item.name}`,
value: item.id,
});
}
}
Like Felix mentioned, Array#filter won't work faster than native for loop, however if you really want it as functional way, here's one possible solution:
const array = [
{ id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } },
{ id: 2, name: 'a2', sub: null },
{ id: 3, name: 'a3', sub: { id: 8, name: 'a3 sub' } },
{ id: 4, name: 'a4', sub: null },
{ id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } },
];
const anotherArray = [
{ id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } },
{ id: 2, name: 'a2', sub: null },
{ id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } },
];
const r = array.filter((elem) => !anotherArray.find(({ id }) => elem.id === id) && elem.sub);
console.log(r);
You can use Array.filter and then Array.some since the later would return boolean instead of the element like Array.find would:
const a1 = [ { id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } }, { id: 2, name: 'a2', sub: null }, { id: 3, name: 'a3', sub: { id: 8, name: 'a3 sub' } }, { id: 4, name: 'a4', sub: null }, { id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } }, ];
const a2 = [ { id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } }, { id: 2, name: 'a2', sub: null }, { id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } }, ];
const result = a1.filter(({id, sub}) => !a2.some(x => x.id == id) && sub)
console.log(result)
You could use JSON.stringify to compare the two objects. It would be better to write a function that compares all properties on the objects recursively.
const array = [
{ id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } },
{ id: 2, name: 'a2', sub: null },
{ id: 3, name: 'a3', sub: { id: 8, name: 'a3 sub' } },
{ id: 4, name: 'a4', sub: null },
{ id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } },
];
const anotherArray = [
{ id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } },
{ id: 2, name: 'a2', sub: null },
{ id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } },
];
const notIn = (array1, array2) => array1.filter(item1 => {
const item1Str = JSON.stringify(item1);
return !array2.find(item2 => item1Str === JSON.stringify(item2))
}
);
console.log(notIn(array, anotherArray));
Ok, let's solve this step by step.
To simplify the process let's suppose that two elements can be considered equals if they both have the same id.
The first approach that I would use is to iterate the first array and, for each element, iterate the second one to check the conditions that you've defined above.
const A = [ /* ... */]
const B = [ /* ... */]
A.filter(el => {
let existsInB = !!B.find(e => {
return e.id === el.id
}
return existsInB && !!B.sub
})
If we are sure that the elements in A and in B are really the same when they have the same ID, we could skip all the A elements without the sub property to perform it up a little bit
A.filter(el => {
if (!el.sub) return false
let existsInB = !!B.find(e => {
return e.id === el.id
}
return existsInB
})
Now, if our arrays are bigger than that, it means that we are wasting a lot of time looking for the element into B.
Usually, in these cases, I transform the array where I look for into a map, like this
var BMap = {}
B.forEach(el => {
BMap[el.id] = el
})
A.filter(el => {
if (!el.sub) return false
return !!BMap[el.id]
})
In this way you "waste" a little bit of time to create your map at the beginning, but then you can find your elements quicker.
From here there could be even more optimizations but I think this is enought for this question
OPTIMIZED VERSION
const array = [{
id: 1,
name: "a1",
sub: {
id: 6,
name: "a1 sub"
}
},
{
id: 2,
name: "a2",
sub: null
},
{
id: 3,
name: "a3",
sub: {
id: 8,
name: "a3 sub"
}
},
{
id: 4,
name: "a4",
sub: null
},
{
id: 5,
name: "a5",
sub: {
id: 10,
name: "a5 sub"
}
},
];
const anotherArray = [{
id: 1,
name: "a1",
sub: {
id: 6,
name: "a1 sub"
}
},
{
id: 2,
name: "a2",
sub: null
},
{
id: 5,
name: "a5",
sub: {
id: 10,
name: "a5 sub"
}
},
];
const dict = anotherArray.reduce((acc, curr) => {
const { id } = curr;
acc[id] = curr;
return acc;
}, {});
const result = array.filter((obj) => {
const search = dict[obj.id];
if (!search && obj.sub) return true;
return false;
});
console.log(result);

Categories

Resources