Get unique values from array values in json array - javascript

I'm writing a code where I need to return uniques values from a JSON array. Here my challenge is, I've got these values as an array for one of the keys.
Here is my code.
let mobilePhones = [{
id: 1,
brand: ["B1", "B2"]
}, {
id: 2,
brand: ["B2"]
}, {
id: 3,
brand: ["B1", "B2"]
}, {
id: 4,
brand: ["B1"]
}, {
id: 5,
brand: ["B2", "B1"]
}, {
id: 6,
brand: ["B3"]
}]
let allBrandsArr = mobilePhones.map(row => {
return row.brand;
});
let uniqueBrands = allBrandsArr.filter((item, index, arry) => (arry.indexOf(item) === index));
console.log(JSON.stringify(uniqueBrands));
Here my expected result is to get ["B1", "B2", "B3"]. Please let me know how can I achieve this.
Updated new sample data:
let mobilePhones = [{
id: 1,
brand: ["B1, B2"]
}, {
id: 2,
brand: ["B2"]
}, {
id: 3,
brand: ["B1, B2"]
}, {
id: 4,
brand: ["B1"]
}, {
id: 5,
brand: ["B2, B1"]
}, {
id: 6,
brand: ["B3"]
}]
let allBrandsArr = mobilePhones.map(row => {
return row.brand;
});
Thanks

You need to use flat for merge sub array then your code was good:
let mobilePhones = [{
id: 1,
brand: ["B1, B2"]
}, {
id: 2,
brand: ["B2"]
}, {
id: 3,
brand: ["B1, B2"]
}, {
id: 4,
brand: ["B1"]
}, {
id: 5,
brand: ["B2, B1"]
}, {
id: 6,
brand: ["B3"]
}]
let allBrandsArr = mobilePhones.map(row => {
return row.brand[0].split(',').map(function(item) {
return item.trim();
});
});
let uniqueBrands = allBrandsArr.flat().filter((item, index, arry) => (arry.indexOf(item) === index));
console.log(JSON.stringify(uniqueBrands));
Reference:
Array.prototype.flat()
After new Data posted i add split with trim.
Reference:
String.prototype.split()
String.prototype.trim()

You can use .flatMap to get all the brand values and pass it to a Set to make it unique.
const uniqueBrands = [...new Set(mobilePhones.flatMap(({
brand
}) => brand))];
let mobilePhones = [{
id: 1,
brand: ["B1", "B2"]
}, {
id: 2,
brand: ["B2"]
}, {
id: 3,
brand: ["B1", "B2"]
}, {
id: 4,
brand: ["B1"]
}, {
id: 5,
brand: ["B2", "B1"]
}, {
id: 6,
brand: ["B3"]
}]
const unique = [...new Set(mobilePhones.flatMap(({
brand
}) => brand))];
console.log(unique);

Related

How can I get the result from arr1 and arr2, When the ID matches I need to copy the content from arr1

How can I get the result from arr1 and arr2, When the ID matches I need to copy the content from arr1
const arr1 = [
{ id: 1, name: "omar" },
{ id: 2, name: "laith" },
{ id: 3, name: "aref" },
]
const arr2 = [
{ id: 1, rating: "good" },
{ id: 2, rating: "very good" },
{ id: 2, rating: "very good" },
{ id: 3, rating: "Excellence" },
{ id: 3, rating: "Excellence" },
]
//expected output
const result = [
{ id: 1, rating: "good", name: "omar" },
{ id: 1, rating: "good", name: "omar" },
{ id: 2, rating: "very good", name: "laith" },
{ id: 3, rating: "Excellence", name: "aref" },
{ id: 3, rating: "Excellence", name: "aref" },
]
use reduce with filter
const arr1 = [ { id: 1, name: "omar" }, { id: 2, name: "laith" }, { id: 3, name: "aref" }, ];
const arr2 = [ { id: 1, rating: "good" }, { id: 2, rating: "very good" }, { id: 2, rating: "very good" }, { id: 3, rating: "Excellence" }, { id: 3, rating: "Excellence" }, ];
const result = arr1.reduce((acc,item) => {
const list = arr2.filter(i => i.id === item.id)
return [...acc, ...list.map(i => ({id: i.id,rating:i.rating, name: item.name}))]
}, [])
console.log(result)
Basically with a loop. Actually 2. Using a temporary object (result) as dictionary (or map) we can make it efficient searching for a match to each id. This is of complexity O(n) basically.
const arr1 = [ { id: 1, name: "omar" }, { id: 2, name: "laith" }, { id: 3, name: "aref" }, ];
const arr2 = [ { id: 1, rating: "good" }, { id: 2, rating: "very good" }, { id: 2, rating: "very good" }, { id: 3, rating: "Excellence" }, { id: 3, rating: "Excellence" }, ];
var result = {}
arr1.forEach(function(item1) {
result[item1.id] = item1;
});
arr2.forEach(function(item2) {
result[item2.id] = (result[item2.id] || item2)
result[item2.id]['rating'] = item2.rating
})
result = Object.values(result)
console.log(result)

filter array of object from another array with multiple elements in javascript

I have object and an array:
const response = [
{ id: 1, product: 'EL' },
{ id: 2, product: 'AC' },
{ id: 3, product: 'AC' },
{ id: 4, product: 'AD' },
{ id: 5, product: 'DE' },
];
const elProd = [
"EL"
"DE"
];
i want to filter out the product which has product code in elProd array.
my expectation is below:
const response = [
{ id: 2, product: 'AC' },
{ id: 3, product: 'AC' },
{ id: 4, product: 'AD' },
];
what I tried :
response.filter(obj => {return obj.product == elProd .includes(obj.product)})
const response = [{
id: 1,
product: 'EL'
},
{
id: 2,
product: 'AC'
},
{
id: 3,
product: 'AC'
},
{
id: 4,
product: 'AD'
},
{
id: 5,
product: 'DE'
},
];
const elProd = [
"EL",
"DE"
];
const filteredresp = response.filter((resp) => elProd.indexOf(resp.product) !== -1);
console.log(filteredresp);
response.filter(obj => {return !elProd.includes(obj.product)});
You almost got it, but you have a typo. You need a comma in the elProd array. Here's the code:
const response = [
{ id: 1, product: "EL" },
{ id: 2, product: "AC" },
{ id: 3, product: "AC" },
{ id: 4, product: "AD" },
{ id: 5, product: "DE" },
];
const elProd = [
"EL", // <-- Add the comma.
"DE",
];
// Don't forget to negate the includes here to exclude those you don't want.
const filtered = response.filter((obj) => !elProd.includes(obj.product));
// Result.
console.log(filtered);
You need only the check with includes.
const
response = [{ id: 1, product: 'EL' }, { id: 2, product: 'AC' }, { id: 3, product: 'AC' }, { id: 4, product: 'AD' }, { id: 5, product: 'DE' }],
elProd = ["EL", "DE"],
result = response.filter(obj => !elProd.includes(obj.product));
console.log(result);
You could use filter and some
const response = [
{ id: 1, product: 'EL' },
{ id: 2, product: 'AC' },
{ id: 3, product: 'AC' },
{ id: 4, product: 'AD' },
{ id: 5, product: 'DE' },
];
const elProd = [
"EL",
"DE"
]
res=response.filter(o=>!elProd.some(p=>o.product==p))
console.log(res)

How to Structure This array, Separate Category and Product

I have single array, I want to separate category and category Product
const product = [{
id: 1,
name: 'Cloth',
cat: ['fashion', 'man', 'women']
}, {
id: 2,
name: 'Shoes',
cat: ['fashion']
}, {
id: 3,
name: "hat",
cat: ['man', 'fashion']
}]
How to Separate category value from Product array.
const cat = ['fashion','man','women']
How to Separate category and Product
const result = [{
cat: 'fashion',
[{
id: 1,
name: 'Cloth'
}, {
id: 2,
name: 'Shoes'
}, {
id: 3,
name: "hat"
}]
}, {
cat: 'man',
[{
id: 1,
name: 'Cloth'
}, {
d: 3,
name: "hat"
}]
}, {
cat: 'women',
[{
id: 1,
name: 'Cloth'
}]
}]
How to develop this type of array please help me. Any one know please help me, Advance tanks for reply
First answer:
let categories = [];
const product = [
{ id: 1, name: "Cloth", cat: ["fashion", "man", "women"] },
{ id: 2, name: "Shoes", cat: ["fashion"] },
{ id: 3, name: "hat", cat: ["man", "fashion"] }
];
product.forEach((p) => {
p.cat.forEach((cat) => {
if(!categories.includes(cat)) {
categories.push(cat)
}
})
})
console.log(categories) // ['fashion','man','women']
If you one to get All categories from product Array.
let allCategories = [];
product.forEach(p => {
allCategories.push(...p.cat);
});
allCategories = [...new Set(allCategories)];
For second question I will use the result of first question:
allCategories.forEach(categorie => {
result.push(
{
cat: categorie,
products : product.filter(p => {
if(p.cat.includes(categorie)) {
return {
id : p.id,
name : p.name
}
}
})
}
)
})

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

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