combining two arrays that have the same field in node js - javascript

I have arrays like these
arr1 = [{
"_id": 1,
"item": "Pencil",
"color": "Red"
},{
"_id":2,
"item": "Pen",
"color": "Yellow"
},{
"_id": 3,
"item": "Pencil",
"color": "Green"
}]
arr2 = [{
"value":"Pencil",
"price":1000,
},{
"value":"Pen",
"price":1500,
}]
How do I combine this arr2 into arr1 with "value" in arr2 and "price" in arr1 as the key? so that it has the following results
res = [{
"_id": 1,
"item": "Pencil",
"color": "Red",
"price": 1000
},{
"_id":2,
"item": "Pen",
"color": "Yellow",
"price": 1500
},{
"_id": 3,
"item": "Pencil",
"color": "Green",
"price": 1000
}]

You can use map. For example:
let arr3 = arr1.map((el1) => {
let found = arr2.find(el2 => el1.item == el2.value)
if (found)
el1.price = found.price
return el1
})
console.log(arr3)

You can use Map collection to have O(1) while mapping the second array:
const uniquePencils = new Map(arr2.map(s => [s.value, s.price]));
const result = arr1.map(a => ({...a, price: uniquePencils.get(a.item)}));
As mdn says about Map collection:
The Map object holds key-value pairs and remembers the original
insertion order of the keys.
So to create a map collection from array we can use map method:
const uniquePencils = new Map(arr2.map(s => [s.value, s.price]));
Then when we map array, we need to give item name(e.g. Pencil) to Map collection to get object from map collection.
arr1.map(a => ({...a, price: uniquePencils.get(a.item)}));
In addition, we've used ... operator. It is called spread syntax. It copies own enumerable properties from a provided object onto a new object.
An example:
let arr1 = [{
"_id": 1,
"item": "Pencil",
"color": "Red"
},{
"_id":2,
"item": "Pen",
"color": "Yellow"
},{
"_id": 3,
"item": "Pencil",
"color": "Green"
}];
let arr2 = [{
"value":"Pencil",
"price":1000,
},{
"value":"Pen",
"price":1500,
}];
const uniquePencils = new Map(arr2.map(s => [s.value, s.price]));
const result = arr1.map(a => ({...a, price: uniquePencils.get(a.item)}));
console.log(result);

Related

Compare array of objects with array

I have an array of objects:
arr1 = [
{
"id": 1,
"color": "blue",
"label": "School",
},
{
"id": 2,
"color": "red",
"label": "Work",
}
]
and a simple array:
arr2 = [ 2, 5 ]
I want to write a method that returns true if one of the object ids from arr1 can be found in arr2. So I could use it with
v-if
later.
What's your suggestion?
let arr1 = [
{
"id": 1,
"color": "blue",
"label": "School",
},
{
"id": 2,
"color": "red",
"label": "Work",
}
]
let arr2 = [ 2, 5 ]
let arr1_id = arr1.map(function (obj) {
return obj.id;
});
function check(array1, array2) {
let intersection = array1.filter(element => array2.includes(element));
if (intersection.length > 0) {
return true
}
else {return false}
}
bool = check(arr1_id,arr2)
console.log(bool)

Removing duplicate value from list of javascript objects in react js

I have react project and in that have a javascript array of object similar to given below and in that object it has a value called category.
const data = [{
"id": 1,
"item": "760",
"price": "$609.05",
"category": "BMW"
}, {
"id": 2,
"item": "Frontier",
"price": "$317.89",
"category": "Nissan"
}, {
"id": 3,
"item": "Odyssey",
"price": "$603.64",
"category": "BMW"
}]
Im mapping through the list and displaying the category as shown below.
{data.map(item => (<span>{item.category}</span>))}
Here, the category duplicates and display several times when there are several similar items. Considering the given data list, the category BMW display twice.
What I want is, even if there are multiple similar categories, I only want to display once. Is this possible and how can I do it?
You could add your categories into a Set
const data = [{
"id": 1,
"item": "760",
"price": "$609.05",
"category": "BMW"
}, {
"id": 2,
"item": "Frontier",
"price": "$317.89",
"category": "Nissan"
}, {
"id": 3,
"item": "Odyssey",
"price": "$603.64",
"category": "BMW"
}]
let categories = new Set()
data.forEach(entry => {categories.add(entry.category) })
categories.forEach(cat => console.log(cat))
There can be various ways to reach the desired result. I would do it with a Set() and destructuring syntax:
{[...new Set(data.map(item => (<span>{item.category}</span>)))]}
const data = [{
"id": 1,
"item": "760",
"price": "$609.05",
"category": "BMW"
}, {
"id": 2,
"item": "Frontier",
"price": "$317.89",
"category": "Nissan"
}, {
"id": 3,
"item": "Odyssey",
"price": "$603.64",
"category": "BMW"
}]
const newData = [...new Set(data.map(item => ("<span>" + item.category + "</span>")))]
console.log(newData);
you can use {data.find(item => (<span>{item.category}</span>))}. The find() method returns the first element in the provided array that satisfies the provided testing function
You can use the filter
let array= data.filter((v,i,a)=>a.findIndex(v2=>(v2.category===v.category))===i)
and
{array.map(item => (<span>{item.category}</span>))}
const data = [{
"id": 1,
"item": "760",
"price": "$609.05",
"category": "BMW"
}, {
"id": 2,
"item": "Frontier",
"price": "$317.89",
"category": "Nissan"
}, {
"id": 3,
"item": "Odyssey",
"price": "$603.64",
"category": "BMW"
}]
function getUniqueArrayBy(arr, key) {
return [...new Map(arr.map(item => [item[key], item])).values()]
}
const filtered = getUniqueArrayBy(data, 'category');
console.log(filtered);
Use native methods .reduce and .map of Array in chain.
const categories = data.reduce((acc, {category}) => {
if (!acc.includes(category)) { // check if there's not such value in accumulator
acc.push(category); // adding category
}
return acc; // returning value
}, []) // [] is an accumulator value
.map(category => <span>{category}</span>); // iterating over result
Piece a cake.

structuring obj array based on their attributes [duplicate]

This question already has answers here:
How can I group an array of objects by key?
(32 answers)
Closed 1 year ago.
can you help me with this problem with js\react?
I'm trying to manage 2 arrays due to obtain a new object based on their shared attribute (Array A: "id" and Array B: "parent")
I think isn't hard but I'm struggling to do it atm :(
Array A
[{
"id": "606f1a2bebb5fb53804dd3d5",
"name": "cc",
}, {
"id": "606f1a30cfe84430c41dce88",
"name": "bb",
}, {
"id": "606f1a4ed2ff554e4ea11b82",
"name": "ff",
}]
Array B
[{
"id": "3344",
"color": "pink",
"parent": "606f1a2bebb5fb53804dd3d5",
}, {
"id": "3453",
"color": "blue",
"parent": "606f1a30cfe84430c41dce88",
}, {
"id": "3331",
"color": "yellow",
"parent": "606f1a4ed2ff554e4ea11b82",
}, {
"id": "4442",
"color": "black",
"parent": "606f1a30cfe84430c41dce88",
}]
I want merge these two arrays and create a new one where the array B objects are split by "id" of array A.
Something like this:
[{
"606f1a2bebb5fb53804dd3d5": [{
"id": "3344",
"color": "pink",
"parent": "606f1a2bebb5fb53804dd3d5",
}]
}, {
"606f1a30cfe84430c41dce88": [{
"id": "3453",
"color": "blue",
"parent": "606f1a30cfe84430c41dce88",
}, {
"id": "4442",
"color": "black",
"parent": "606f1a30cfe84430c41dce88",
}]
}, {
"606f1a4ed2ff554e4ea11b82": [{
"id": "3331",
"color": "yellow",
"parent": "606f1a4ed2ff554e4ea11b82",
}]
}]
Thanks very much guys
You just need array b for grouping and another object for keeping track of the max key inside of a group.
const
data = [{ id: "3344", color: "pink", parent: "606f1a2bebb5fb53804dd3d5" }, { id: "3453", color: "blue", parent: "606f1a30cfe84430c41dce88" }, { id: "3331", color: "yellow", parent: "606f1a4ed2ff554e4ea11b82" }, { id: "4442", color: "black", parent: "606f1a30cfe84430c41dce88" }],
max = {},
result = data.reduce((r, o) => {
max[o.parent] = (max[o.parent] || 0) + 1;
(r[o.parent] ??= {})[max[o.parent]] = o;
return r;
}, {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I think you can loop through the items and then find the parent
let arrayC = [];
arrayB.forEach(item => {
let parent = array1.find(e => e.id === item.parent);
// do something here to combine it into one object
// then arrayC.push(newItem);
});
https://codesandbox.io/s/boring-snowflake-brksj?file=/src/index.js
const result = arrayA.reduce((acc, arrayAItem) => {
return {
...acc,
[arrayAItem.id]: arrayB.filter(
(arrayBItem) => arrayBItem.parent === arrayAItem.id
)
};
}, {});
}]
You can do this with map and filter functions of array.
const newArray = array1.map(array1Item => {
return { [array1Item.id]: array2.filter(array2Item => array2Item.parent === array1Item.id)}
})
Based on the two arrays that you have, I assume that they are only linked by their "parent" ids. If this is the case, you can reduce the B array using the A array as an accumulator.
const a = [
{ "id": "606f1a2bebb5fb53804dd3d5" , "name": "cc" },
{ "id": "606f1a30cfe84430c41dce88" , "name": "bb" },
{ "id": "606f1a4ed2ff554e4ea11b82" , "name": "ff" },
];
const b = [
{ "id": "3344" , "color": "pink" , "parent": "606f1a2bebb5fb53804dd3d5" },
{ "id": "3453" , "color": "blue" , "parent": "606f1a30cfe84430c41dce88" },
{ "id": "3331" , "color": "yellow" , "parent": "606f1a4ed2ff554e4ea11b82" },
{ "id": "4442" , "color": "black" , "parent": "606f1a30cfe84430c41dce88" },
];
const c = Object
.entries(b.reduce((acc, { id, color, parent }) =>
({ ...acc, [parent]: {
...acc[parent],
colors: [...acc[parent].colors, { id, color } ]
}}),
Object.fromEntries(a.map(({ id, name }) =>
[ id, { name, colors: [] } ]))))
.map(([ id, value ]) => value);
console.log(c);
.as-console-wrapper { top: 0; max-height: 100% !important; }

How can I clone objects in JavaScript based on object's array

Say I have an array of objects like this:
let cars = [
{
"name": "Ford",
"color": ["Blue", "Red"]
},
{
"name": "Toyota",
"color": ["Blue"]
}
]
How can, without using a for loop, flatten the array out (flatMap perhaps?) so my array looks like this:
let cars = [
{
"name": "Ford",
"color": "Blue"
},
{
"name": "Ford",
"color": "Red"
},
{
"name": "Toyota",
"color": "Blue"
}
]
The reason for not wanting to loop through is that my array is large and I have multiple arrays in the object that I wish to "explode" like this (so I end up iterating over the array 5 times).
With .reduce() and .forEach() combination as the following:
const cars = [{ "name": "Ford", "colors": ["Blue", "Red"] }, { "name": "Toyota", "colors": ["Blue"] }];
const result = cars.reduce((a, c) => {
c.colors.forEach(e => {
a.push({ name: c.name, colors: e });
});
return a;
}, []);
console.log(result);
I hope this helps!
You can use flatMap
let cars = [{
"name": "Ford",
"colors": ["Blue", "Red"]
},
{
"name": "Toyota",
"colors": ["Blue"]
}
]
let result = cars.flatMap(e => {
return e.colors.map((color)=>({name:e.name,color}))
});
console.log(result);
For multiple props (just make sure each of them has at least one type and color)
let cars = [
{
"name": "Ford",
"colors": ["Blue", "Red"],
"type": ["4WD", "RWD"]
},
{
"name": "Toyota",
"colors": ["Blue"],
"type":["TYPE"]
}
]
function flatProps(arr,props){
arr = [...arr]; //to perserve the original array
props.forEach(prop => {
arr = arr.flatMap(e => {
return e[prop].map((value) => {
let r = Object.assign({},e);
r[prop] = value;
return r;
})
});
})
return arr;
}
console.log(flatProps(cars,["colors","type"]));

Accessing nest elements by their keys with d3.js

So I have the following nest:
var myNest = [
{"key":"1","values":[...]},
{"key":"2","values":[...]},
{"key":"3","values":[...]},
]
How can I access these elements using their keys?
I know I can access them by their index
myNext[0] //return elements with key=="1"
myNest[1] //return elements with key=="2"
But what I would like to do is:
myNest["1"] //return elements with key=="1"
myNest["2"] //return elements with key=="2"
Thanks
Use map() instead of entries() when building your nest. You probably did something similar to this:
var products = [{
"id": 1,
"name": "Cat Hat",
"price": 49
}, {
"id": 2,
"name": "Unicorn Boots",
"price": 139
}, {
"id": 3,
"name": "Pink Woolly Jumper",
"price": 34
}];
var productsById = d3.nest()
.key(function(p) {
return p.id;
})
.entries(products);
console.log(productsById)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
If instead you use map():
var products = [{
"id": 1,
"name": "Cat Hat",
"price": 49
}, {
"id": 2,
"name": "Unicorn Boots",
"price": 139
}, {
"id": 3,
"name": "Pink Woolly Jumper",
"price": 34
}];
var productsById = d3.nest()
.key(function(p) {
return p.id;
})
.map(products);
console.log(productsById)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
You get a map where you can access objects by their key directly, e.g. with productsById["2"] in this example.
You could us a hash table, where the key of your object is the key for the object itselft.
For ES6 I suggest to use a Map:
var myNest = [{ key: "1", values: [1, 4] }, { key: "2", values: [2, 5] }, { key: "3", values: [3, 6] }],
hash = Object.create(null);
myNest.forEach(function (a) {
hash[a.key] = a;
});
console.log(hash['2']);

Categories

Resources