Extract data from array if IDs match - javascript

I am struggling to find out a solution to my problem, but at the moment I cannot come up with the right one.
When I have my two arrays of objects I want to filter based on category IDs and extract the data from the second one into a new array for example :
const array1 = [
{id: 1, name: 'Tropical'},
{id: 2, name: 'Common'}
]
const array2 = [
{id:1, name: 'Banana', category_id: 1},
{id:2, name: 'Mango', category_id: 1},
{id:3, name: 'Apple', category_id: 2},
]
And when click happens I detect the first ID and render the new array only with data that matches the ID.
Click Tropical
New array :
[
{id:1, name: 'Banana', category_id: 1},
{id:2, name: 'Mango', category_id: 1},
]
I would be happy if someone give me a hint on how can I tackle this problem. Thanks !

Correct me if I am wrong, So you need a function that received a categoryId and you need to filter out array2 based on that category_id
You can try this
const array1 = [{
id: 1,
name: 'Tropical'
},
{
id: 2,
name: 'Common'
}
]
const array2 = [{
id: 1,
name: 'Banana',
category_id: 1
},
{
id: 2,
name: 'Mango',
category_id: 1
},
{
id: 3,
name: 'Apple',
category_id: 2
},
]
function categoryFruits(categoryId) {
return array2.filter(obj => obj.id === categoryId)
}
console.log(categoryFruits(3));

Use reduce to map over each item in array1 and filter to grab the items of that category_id
const array1 = [{
id: 1,
name: 'Tropical'
},
{
id: 2,
name: 'Common'
}
]
const array2 = [{
id: 1,
name: 'Banana',
category_id: 1
},
{
id: 2,
name: 'Mango',
category_id: 1
},
{
id: 3,
name: 'Apple',
category_id: 2
},
]
const obj = array1.reduce((acc, cur) => {
acc[cur.name] = array2.filter(v => v.category_id === cur.id)
return acc
}, {})
console.log(obj)

You could do something like filtering array2 and taking all the elements that have Tropical as name in array1.
const array1 = [
{id: 1, name: 'Tropical'},
{id: 2, name: 'Common'}
]
const array2 = [
{id:1, name: 'Banana', category_id: 1},
{id:2, name: 'Mango', category_id: 1},
{id:3, name: 'Apple', category_id: 2},
]
// take tropical friuts
let tropicalFriuts = array2.filter(x => x.category_id === array1.filter(y => y.name === 'Tropical')[0].id);
console.log(tropicalFriuts);

If I understood your problem you want before find the id, based on the name of the category, and later filter array2 data based on this id.
const array1 = [{
id: 1,
name: 'Tropical'
},
{
id: 2,
name: 'Common'
}
]
const array2 = [{
id: 1,
name: 'Banana',
category_id: 1
},
{
id: 2,
name: 'Mango',
category_id: 1
},
{
id: 3,
name: 'Apple',
category_id: 2
},
]
const id_key = array1.find(item=>item.name === 'Tropical').id;
const result = array2.filter(item=>item.category_id === id_key);
console.log(result);

Related

Get specific value from array object in a single line in typescript

I have a following array
const _array = [{id: 1, name: 'Adam'}, {id:3, name: 'Crystal'}, {id:2, name: 'Bob'}, {id: 4, name: 'Daisy'}];
How to write a single line of code in typescript to get item where name equal to Crystal from the array?
You can use array find method like following:
const _array = [
{ id: 1, name: "Adam" },
{ id: 3, name: "Crystal" },
{ id: 2, name: "Bob" },
{ id: 4, name: "Daisy" },
];
const item = _array.find((item) => item.name === "Crystal");
console.log(item);
Output
{ id: 3, name: 'Crystal' }

Lodash Merge Two Arrays and categorize it

i neeed to merge two arrays: Categories and Products. Each product has a category object. I need to organize by category, include the category object and keep the empty categories. GroupBy function include only one parameter.
const Categories= [
{id: 1, 'name': 'category1'}
{id: 2, 'name': 'category2'},
{id: 3, 'name': 'category3'},
{id: 4, 'name': 'category4'},
]
const Products= [
{id: 1, 'name': 'product1', category: {id: 1, name: 'category1'}},
{id: 2, 'name': 'product2', category: {id: 1, name: 'category1'}},
{id: 3, 'name': 'product3', category: {id: 2, name: 'category2'}},
{id: 4, 'name': 'product4', category: {id: 2, name: 'category2'}},
]
expected result
const result = [
{
category: {id: 1, name: 'category1'},
products:[{id:1, name: 'produt1'}, {id: 2, name: 'produto1'} ]
},
{
category: {id: 2, name: 'category2'},
products:[{id:3, name: 'produt3'}, {id: 4, name: 'produto4'} ]
},
{
category: {id: 3, name: 'category3'},
products:[]
},
{
category: {id: 4, name: 'category4'},
products:[]
},
]
attempts:
for (i = 0; i < categoriesJson.length; i++) {
categoriesJson[i] = _.assign({}, categoriesJson[i], { products: [] })
for (j = 0; j < productsJson.length; j++) {
if(productsJson[j].categoryId.objectId === categoriesJson[i].objectId){
categoriesJson[i].products.push(productsJson[j])
}
}
}
Concat the Categories (formatted by to a Product format) to the Products, group by the category.id, and then map each group - category is taken from the 1st item, while products are the the items in groups, without the category, and empty items are rejected:
const Products = [{"id":1,"name":"product1","category":{"id":1,"name":"category1"}},{"id":2,"name":"product2","category":{"id":1,"name":"category1"}},{"id":3,"name":"product3","category":{"id":2,"name":"category2"}},{"id":4,"name":"product4","category":{"id":2,"name":"category2"}}]
const Categories = [{"id":1,"name":"category1"},{"id":2,"name":"category2"},{"id":3,"name":"category3"},{"id":4,"name":"category4"}]
const result = _(Products)
.concat(Categories.map(category => ({ category })))
.groupBy('category.id')
.map(group => ({
category: _.head(group).category,
products: _(group)
.map(o => _.omit(o, 'category'))
.reject(_.isEmpty)
.value()
}))
.value()
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
And the same idea with lodash/fp. Wrap the _.flow() with the _.useWith() function, and preformat the Categories (2nd param) to fit the Categories. The rest is similar to the lodash chain.
const { useWith, identity, flow, concat, groupBy, map, head, omit, reject, isEmpty } = _
const formatProducts = flow(map(omit('category')), reject(isEmpty))
const fn = useWith(flow(
concat,
groupBy('category.id'),
map(group => ({
category: head(group).category,
products: formatProducts(group)
}))
), [identity, map(category => ({ category }))])
const Products = [{"id":1,"name":"product1","category":{"id":1,"name":"category1"}},{"id":2,"name":"product2","category":{"id":1,"name":"category1"}},{"id":3,"name":"product3","category":{"id":2,"name":"category2"}},{"id":4,"name":"product4","category":{"id":2,"name":"category2"}}]
const Categories = [{"id":1,"name":"category1"},{"id":2,"name":"category2"},{"id":3,"name":"category3"},{"id":4,"name":"category4"}]
const result = fn(Products, Categories)
console.log(result)
<script src='https://cdn.jsdelivr.net/g/lodash#4(lodash.min.js+lodash.fp.min.js)'></script>
If lodash is not a requirement in the solution, this is how I did it with plain javascript;
const Categories= [
{id: 1, 'name': 'category1'},
{id: 2, 'name': 'category2'},
{id: 3, 'name': 'category3'},
{id: 4, 'name': 'category4'}
];
const Products= [
{id: 1, 'name': 'product1', category: {id: 1, name: 'category1'}},
{id: 2, 'name': 'product2', category: {id: 1, name: 'category1'}},
{id: 3, 'name': 'product3', category: {id: 2, name: 'category2'}},
{id: 4, 'name': 'product4', category: {id: 2, name: 'category2'}},
];
const result = [];
for (let index in Categories) {
let category_id = Categories[index].id;
result.push({
category: Categories[index],
products: GetProductsWithCategoryId(category_id)
});
}
function GetProductsWithCategoryId(category_id) {
let products = [];
for (let index in Products) {
if (Products[index].category.id == category_id) {
products.push({
id: Products[index].id,
name: Products[index].name
});
}
}
return products;
}
console.log("result:", result);
Using reduce, create a mappedProducts object which groups the Products based on the category.id. Like this:
{
"1": [{ id: 1, name: "product1" }, { id: 2, name: "product2" }],
"2": [{ id: 3, name: "product3" }, { id: 4, name: "product4" }]
}
Then, map the Categories array and get the output for each category
const Categories=[{id:1,name:"category1"},{id:2,name:"category2"},{id:3,name:"category3"},{id:4,name:"category4"},],
Products=[{id:1,name:"product1",category:{id:1,name:"category1"}},{id:2,name:"product2",category:{id:1,name:"category1"}},{id:3,name:"product3",category:{id:2,name:"category2"}},{id:4,name:"product4",category:{id:2,name:"category2"}}];
const mappedProducts = Products.reduce((acc, { category, ...rest }) => {
acc[category.id] = acc[category.id] || [];
acc[category.id].push(rest)
return acc;
}, {})
const output = Categories.map(category => ({
category,
products: mappedProducts[category.id] || []
}))
console.log(output)
In a single function. Lodash is not necessary:
const Categories = [
{ id: 1, name: "category1" },
{ id: 2, name: "category2" },
{ id: 3, name: "category3" },
{ id: 4, name: "category4" }
];
const Products = [
{ id: 1, name: "product1", category: { id: 1, name: "category1" } },
{ id: 2, name: "product2", category: { id: 1, name: "category1" } },
{ id: 3, name: "product3", category: { id: 2, name: "category2" } },
{ id: 4, name: "product4", category: { id: 2, name: "category2" } }
];
function combine(categories, products) {
return categories.reduce((list, category) => {
const nextItem = {
category,
products: [
products.filter(p => p.category.id === category.id).map(
({ id, name }) => ({
id,
name
})
)
]
};
list.push(nextItem);
return list;
}, []);
}
const result = combine(Categories, Products)
Now for your information, if you had a huge list of categories and/or products, this wouldn't be the ideal solution as there is a lot of looping involved. Instead, you would cache products in such a way that you only ever need to look at a given product once (rather than looking at every product for every category). With a small data set, this optimization isn't necessary.

How to Add new key and value to array in javascript?

I have two array, lets suppose have below value of array: "
var array1 = [
{Id: "809cd136-02c7-4cc8-b9de-04fd3359b265", Name: "testing"},
{Id: "609d3a78-8f7c-4843-acdb-2dcfc73c0d96", Name: "Delhi"},
{Id: "264d54cb-b104-48ed-91db-673327ae8d0e", Name: "rohit-auditor"},
{Id: "ce9691b3-dc55-4d30-baf4-7987c2b49b3e", Name: "test"},
{Id: "284e9e98-8ed7-4fb7-b09f-5d1f2a668b15", Name: "aman"}
]
and second array is :
var array2 = ["809cd136-02c7-4cc8-b9de-04fd3359b265", "609d3a78-8f7c-4843-acdb-2dcfc73c0d96"]
Now i want to add one new key value in array1 only in those object whose value is equal to array one. In other words in want to match both array and want to add "status = true" in those that is having equal value.
new key want to add is :
{status: true}
Now my new array should be:
[
{Id: "809cd136-02c7-4cc8-b9de-04fd3359b265", Name: "testing", status: true},
{Id: "609d3a78-8f7c-4843-acdb-2dcfc73c0d96", Name: "Delhi", status: true},
{Id: "264d54cb-b104-48ed-91db-673327ae8d0e", Name: "rohit-auditor"},
{Id: "ce9691b3-dc55-4d30-baf4-7987c2b49b3e", Name: "test"},
{Id: "284e9e98-8ed7-4fb7-b09f-5d1f2a668b15", Name: "aman"}
]
Hope you understand.
Thanks in advance,
You could use forEach and find like this:
let array1=[{Id:"809cd136-02c7-4cc8-b9de-04fd3359b265",Name:"testing"},{Id:"609d3a78-8f7c-4843-acdb-2dcfc73c0d96",Name:"Delhi"},{Id:"264d54cb-b104-48ed-91db-673327ae8d0e",Name:"rohit-auditor"},{Id:"ce9691b3-dc55-4d30-baf4-7987c2b49b3e",Name:"test"},{Id:"284e9e98-8ed7-4fb7-b09f-5d1f2a668b15",Name:"aman"}],
array2=["809cd136-02c7-4cc8-b9de-04fd3359b265","609d3a78-8f7c-4843-acdb-2dcfc73c0d96"]
array2.forEach(id => {
let found = array1.find(a => a.Id === id);
if(found)
found.status = true
})
console.log(array1)
The if check is there to check if the Id in array2 exists in array1. If every Id in array2 exists in array1, you can simply change it to:
array1.find(a => a.Id === id).status = true
You can use Array#map method to iterate and create a new array and then use Array#includes method to check the value present in the array2. Where use ES6 spread syntax to combine both objects.
var newArray = array1.map(o => array2.includes(o.Id) ? {...o, ...add} : { ...add })
var array1 = [{
Id: "809cd136-02c7-4cc8-b9de-04fd3359b265",
Name: "testing"
},
{
Id: "609d3a78-8f7c-4843-acdb-2dcfc`Array#forEach`73c0d96",
Name: "Delhi"
},
{
Id: "264d54cb-b104-48ed-91db-673327ae8d0e",
Name: "rohit-auditor"
},
{
Id: "ce9691b3-dc55-4d30-baf4-7987c2b49b3e",
Name: "test"
},
{
Id: "284e9e98-8ed7-4fb7-b09f-5d1f2a668b15",
Name: "aman"
}
]
var array2 = ["809cd136-02c7-4cc8-b9de-04fd3359b265", "609d3a78-8f7c-4843-acdb-2dcfc73c0d96"]
var add = {
status: true
};
var newArray = array1.map(o => array2.includes(o.Id) ? {...o, ...add} : { ...add })
console.log(newArray);
If you want to update the original array then simply iterate over the array using Array#forEach method and add an additional property using Object.assign if necessary.
array1.forEach(o => array2.includes(o.Id) && Object.assign(o,add))
var array1 = [{
Id: "809cd136-02c7-4cc8-b9de-04fd3359b265",
Name: "testing"
},
{
Id: "609d3a78-8f7c-4843-acdb-2dcfc73c0d96",
Name: "Delhi"
},
{
Id: "264d54cb-b104-48ed-91db-673327ae8d0e",
Name: "rohit-auditor"
},
{
Id: "ce9691b3-dc55-4d30-baf4-7987c2b49b3e",
Name: "test"
},
{
Id: "284e9e98-8ed7-4fb7-b09f-5d1f2a668b15",
Name: "aman"
}
]
var array2 = ["809cd136-02c7-4cc8-b9de-04fd3359b265", "609d3a78-8f7c-4843-acdb-2dcfc73c0d96"]
var add = {
status: true
};
array1.forEach(o => array2.includes(o.Id) && Object.assign(o, add))
console.log(array1);
A simple map & indexOf will be enough
var array1 = [
{Id: "809cd136-02c7-4cc8-b9de-04fd3359b265", Name: "testing"},
{Id: "609d3a78-8f7c-4843-acdb-2dcfc73c0d96", Name: "Delhi"},
{Id: "264d54cb-b104-48ed-91db-673327ae8d0e", Name: "rohit-auditor"},
{Id: "ce9691b3-dc55-4d30-baf4-7987c2b49b3e", Name: "test"},
{Id: "284e9e98-8ed7-4fb7-b09f-5d1f2a668b15", Name: "aman"}
]
var array2 = ["809cd136-02c7-4cc8-b9de-04fd3359b265", "609d3a78-8f7c-4843-acdb-2dcfc73c0d96"]
var result=array1.map(el=>{
if(array2.indexOf(el.Id)>-1){
el.status=true
}
return el
})
You have to compare element of second array with id's of element of first array and add key (status) to those matching found.
var array1 = [{Id: "809cd136-02c7-4cc8-b9de-04fd3359b265",Name: "testing"},{Id: "609d3a78-8f7c-4843-acdb-2dcfc73c0d96", Name: "Delhi"},{Id: "264d54cb-b104-48ed-91db-673327ae8d0e", Name: "rohit-auditor"},{Id: "ce9691b3-dc55-4d30-baf4-7987c2b49b3e", Name: "test"},{Id: "284e9e98-8ed7-4fb7-b09f-5d1f2a668b15", Name: "aman"}];
var array2 = ["809cd136-02c7-4cc8-b9de-04fd3359b265", "609d3a78-8f7c-4843-acdb-2dcfc73c0d96"];
array2.forEach(function(secondElem) {
let matchingElemInFirstArr = array1.find(el=>el.Id==secondElem);
matchingElemInFirstArr ['status']=true;
});
console.log(array1);

Using Lodash or vanilla JS what is the most efficient way to filter an array based on object keys?

I have two arrays of objects:
array1 = [
{id:1, name: 'one'},
{id:4, name: 'four'}
]
array2 = [
{id:1, name: 'one'},
{id:2, name: 'two'},
{id:3, name: 'three'},
{id:5, name: 'five'},
{id:6, name: 'six'},
{id:7, name: 'seven'}
]
I would like to remove any object from array1 who's id does not exist in array2.
so my expect result would be:
array1 = [
{id:1, name:'one'}
]
Use lodash's _.intersectionBy():
var array1 = [
{id:1, name: 'one'},
{id:4, name: 'four'}
];
array2 = [
{id:1, name: 'one'},
{id:2, name: 'two'},
{id:3, name: 'three'},
{id:5, name: 'five'},
{id:6, name: 'six'},
{id:7, name: 'seven'}
];
var result = _.intersectionBy(array1, array2, 'id');
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
A fast and readable option would be:
var referenceKeys = array2.map(function(entity) { return entity.id; });
var result = array1.filter(function(entity) {
return referenceKeys.indexOf(entity.id) !== -1;
});
But no guarantee that it's the fastest in all dimensions. (Number of repeats, length of array1, length of array2).
You could use a standard approach by using a hash table which uses just one iteration for both arrays.
var array1 = [{ id: 1, name: 'one' }, { id: 4, name: 'four' }],
array2 = [{ id: 1, name: 'one' }, { id: 2, name: 'two' }, { id: 3, name: 'three' }, { id: 5, name: 'five' }, { id: 6, name: 'six' }, { id: 7, name: 'seven' }],
hash = Object.create(null),
result;
array2.forEach(function (o) {
hash[o.id] = true;
});
result = array1.filter(function (o) {
return hash[o.id];
});
console.log(result);
You can use a Set for this:
const seenIds = array2.reduce((set, o) => set.add(o.id), new Set());
const result = array1.filter(o => seenIds.has(o.id));

Combining objects on two arrays based on commonly shared ids

I have two arrays that contain objects. Objects on the first array contain an id, name and age.
I have tried many answers that I have found on StackOverflow such as this one and this one and elsewhere online, however it is proving quite tricky and I am unable to get this working.
var arrOne = [
{id: 1, name: 'Raul', age: 18},
{id: 2, name: 'Sarah', age: 20},
{id: 3, name: 'Sanchez', age: 30}
];
The second array contains an id that is related to the users in the first array and and an associated image.
var arrOne = [
{id: 1, image: 'raulrod.jpg'},
{id: 2, image: 'saz.jpg'},
{id: 1, image: 'hola.jpg'},
{id: 3, image: 'qtal.jpg'},
{id: 1, image: 'senor.jpg'},
{id: 3, image: 'ciao.jpg'},
];
After they are combined I am looking for a result like this with each object combining the objects in both arrays based on the id.
var finalArr = [
{id: 1, name: 'Raul', age: 18 image: 'raulrod.jpg'},
{id: 1, name: 'Raul', age: 18 image: 'hola.jpg'},
{id: 1, name: 'Raul', age: 18 image: 'senor.jpg'},
{id: 2, name: 'Raul', age: 20 image: 'saz.jpg'}
{id: 3, name: 'Raul', age: 30 image: 'ciao.jpg'},
{id: 3, name: 'Raul', age: 30 image: 'qtal.jpg'},
];
With plain ES6, you could map the a new object with the properties of arrOne and, with Array#find, the properties of the related object of arrTwo.
If needed, you could later sort the result by id.
var arrOne = [{ id: 1, name: 'Raul', age: 18 }, { id: 2, name: 'Sarah', age: 20 }, { id: 3, name: 'Sanchez', age: 30 }],
arrTwo = [{ id: 1, image: 'raulrod.jpg' }, { id: 2, image: 'saz.jpg' }, { id: 1, image: 'hola.jpg' }, { id: 3, image: 'qtal.jpg' }, { id: 1, image: 'senor.jpg' }, { id: 3, image: 'ciao.jpg' }],
result = arrTwo.map(a => Object.assign({}, a, arrOne.find(b => a.id === b.id)));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use array.map and array.find proptotypes:
var arrOne = [
{id: 1, name: 'Raul', age: 18},
{id: 2, name: 'Sarah', age: 20},
{id: 3, name: 'Sanchez', age: 30}
];
var arrTwo = [
{id: 1, image: 'raulrod.jpg'},
{id: 2, image: 'saz.jpg'},
{id: 1, image: 'hola.jpg'},
{id: 3, image: 'qtal.jpg'},
{id: 1, image: 'senor.jpg'},
{id: 3, image: 'ciao.jpg'}
];
var finalArr = arrTwo.map(item => {
var correspondingObj = arrOne.find(obj => obj.id === item.id)
item.name = correspondingObj.name;
item.age = correspondingObj.age;
return item;
});
console.log(finalArr);
Actually, https://stackoverflow.com/a/19480257/5809250 should help you.
Have you included underscore - http://underscorejs.org/#extend?
If you do not want to include underscore, you may use [assign][3] function.
Also, I wrote the example. It is not so perfect so you may try to improve it by yourself.

Categories