How to find matches in an array with objects and change property? - javascript

When names match in object property "name" I want to change this property to "TV(1)" for the first match and increase a counter for every next match, but it's doesn't work for me (please run code to see the problem), how I can change array with objects regarding that?
const array = [
{name: "TV", price: 12323, id: 321 },
{name: "Kettle", price: 123, id: 1211 },
{name: "TV", price: 3434, id: 3434312 },
{name: "Car", price: 12343, id: 123123123 },
{name: "TV", price: 4554, id: 2313123123311 }
]
const nameIsMatch = (name, id) => {
let count = 0
return array.map((item) => {
const condition = item.name === name && item.id !== id
const formattedName = `${item.name}(${count += 1})`
return {
price: item.price,
name: condition ? formattedName : item.name,
id: item.id
}
})
}
array.forEach((el) => {
console.log(nameIsMatch(el.name, el.id))
})

The easy fix is to just rework a tiny bit of code with the old technique of moving things around to where they belong:
return array.map((item) => {
return {
price: item.price,
name: (item.name === name && item.id !== id) ? `${item.name}(${count += 1})` : item.name,
id: item.id
}
})
It's now a bit of a mess due to the ternary, so you could always unwind that a bit:
return array.map(item => {
// Make a copy of `item`
let i = { ...item };
// Override if necessary
if (item.name === name && item.id !== id) {
i. name = `${item.name}(${count += 1})`;
}
return i;
})
Where that's not as concise, but it's a lot more clear.

Use an object that keeps a counter for each name.
const array = [
{name: "TV", price: 12323, id: 321 },
{name: "Kettle", price: 123, id: 1211 },
{name: "TV", price: 3434, id: 3434312 },
{name: "Car", price: 12343, id: 123123123 },
{name: "TV", price: 4554, id: 2313123123311 }
];
const nameIsMatch = (array) => {
let counts = {};
return array.map(({
name,
price,
id
}) => {
let count = counts[name] || 1;
const formattedName = `${name}(${count})`
counts[name] = count + 1;
return {
price,
name: formattedName,
id
}
})
}
console.log(nameIsMatch(array))

You can use the following code
const array = [
{name: "TV", price: 12323, id: 321 },
{name: "Kettle", price: 123, id: 1211 },
{name: "TV", price: 3434, id: 3434312 },
{name: "Car", price: 12343, id: 123123123 },
{name: "TV", price: 4554, id: 2313123123311 }];
const hash = {};
array.forEach(function(obj){
if(!hash[obj.name])
hash[obj.name] = 1;
obj.name = `${obj.name}(${hash[obj.name]++})`;
})
console.log(array)

const array = [
{name: "TV", price: 12323, id: 321 },
{name: "Kettle", price: 123, id: 1211 },
{name: "TV", price: 3434, id: 3434312 },
{name: "Car", price: 12343, id: 123123123 },
{name: "TV", price: 4554, id: 2313123123311 }];
const result = array.map((data, index) => {
if(data.name === 'TV') {
return {...data, name:'TV'+'('+index+')'}
}
return data
})
console.info(result)
You have to use like this It's working for me as per your output

you could actually do it one by one even though this step will take a lot of time, however this will gives you a better understanding.
Data
const array = [
{name: "TV", price: 12323, id: 321 },
{name: "Kettle", price: 123, id: 1211 },
{name: "TV", price: 3434, id: 3434312 },
{name: "Car", price: 12343, id: 123123123 },
{name: "TV", price: 4554, id: 2313123123311 }
]
function to get all the Data Name. This will return [ 'TV', 'Kettle', 'Car' ]
function getAllDataName(arr){
let a = arr.map((dataName) => dataName["name"] )
let b = []
a.filter((dataName) => {
// includes() used to find the intersect of array with particular data
if(!b.includes(dataName)){
b.push(dataName)
}
})
return b
}
function to map all the Data Name accordingly
function remapDataName(arr, dataName){
let s = [...arr] //
console.log(s)
console.log(dataName)
dataName.forEach(function(val, counter = 0){
counter = 0
s.forEach(function(data){
if(data["name"] == val){
data["name"] += "(" + counter++ + ")"
}
})
})
return s
}
call those functions
let objectName = getAllDataName(array)
let objectNameMapped = remapDataName(array, objectName)
objectNameMapped will print
[
{ name: 'TV(0)', price: 12323, id: 321 },
{ name: 'Kettle(0)', price: 123, id: 1211 },
{ name: 'TV(1)', price: 3434, id: 3434312 },
{ name: 'Car(0)', price: 12343, id: 123123123 },
{ name: 'TV(2)', price: 4554, id: 2313123123311 }
]

JavaScript:
const array = [
{ name: 'TV', price: 12323, id: 321 },
{ name: 'Kettle', price: 123, id: 1211 },
{ name: 'TV', price: 3434, id: 3434312 },
{ name: 'Car', price: 12343, id: 123123123 },
{ name: 'TV', price: 4554, id: 2313123123311 },
];
const tv_array = [];
let count = 1
for (let i = 0; i < array.length; i++) {
let name = array[i].name;
if (name === 'TV') {
tv_array.push({
name: `TV(${count})`,
price: array[i].price,
id: array[i].id,
})
count++
} else {
tv_array.push(array[i]);
}
}
console.log(tv_array);
Output:
[
{ name: 'TV(1)', price: 12323, id: 321 },
{ name: 'Kettle', price: 123, id: 1211 },
{ name: 'TV(2)', price: 3434, id: 3434312 },
{ name: 'Car', price: 12343, id: 123123123 },
{ name: 'TV(3)', price: 4554, id: 2313123123311 }
]

Related

Problem with grouping array of objects in JS [duplicate]

This question already has answers here:
How to loop an object in React?
(8 answers)
Closed 1 year ago.
I have such array of objects:
[{id: 1, name: 'Apple', category: 'Fruit'}
{id: 2, name: 'Melon', category: 'Fruit'}
{id: 3, name: 'iPhone', category: 'Phone'}
{id: 4, name: 'Samsung Galaxy Note 8', category: 'Phone'}
{id: 5, name: 'Playstation 5', category: 'Entertainment'}]
and what I wanted to achieve is to combine product names by category and show them like:
Fruit
Apple
Melon
Phone
iPhone
Samsung Galaxy Note 8
Entertainment
Playstation 5
So, what I tried to achieve that is
var groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
const products = [{id: 1, name: 'Apple', category: 'Fruit'}
{id: 2, name: 'Melon', category: 'Fruit'}
{id: 3, name: 'iPhone', category: 'Phone'}
{id: 4, name: 'Samsung Galaxy Note 8', category: 'Phone'}
{id: 5, name: 'Playstation 5', category: 'Entertainment'}]
console.log(groupBy([products], 'category'));
You have to adjust your reduce a bit:
const mapping = arr.reduce((obj, entry) => {
obj[entry.category] = obj[entry.category] ? [...obj[entry.category], entry] : [entry]
return obj;
}, {})
resulting in
{
Entertainment: [{
category: "Entertainment",
id: 5,
name: "Playstation 5"
}],
Fruit: [{
category: "Fruit",
id: 1,
name: "Apple"
}, {
category: "Fruit",
id: 2,
name: "Melon"
}],
Phone: [{
category: "Phone",
id: 3,
name: "iPhone"
}, {
category: "Phone",
id: 4,
name: "Samsung Galaxy Note 8"
}]
}
And you can adjust what you want to save by changing entry to a desired value of entry.
I would approach your groupBy method like this:
function groupBy(data, key, value) {
const groups = {};
data.forEach(element => {
let subkey = element[key];
if (!(subkey in groups)) {
groups[subkey] = [element[value]];
} else {
groups[subkey].push(element[value]);
}
});
return groups;
}
console.log(groupBy(products, "category", "name")
You loop over every element, and if the specified key is not already in the groups object it will be added. if it's already added we just add the new element to the array.
This is an example return value of the groupBy function:
{
Fruit: [ 'Apple', 'Melon' ],
Phone: [ 'iPhone', 'Samsung Galaxy Note 8' ],
Entertainment: [ 'Playstation 5' ]
}
To generate HTML code
var groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
const products = [{id: 1, name: 'Apple', category: 'Fruit'},
{id: 2, name: 'Melon', category: 'Fruit'},
{id: 3, name: 'iPhone', category: 'Phone'},
{id: 4, name: 'Samsung Galaxy Note 8', category: 'Phone'},
{id: 5, name: 'Playstation 5', category: 'Entertainment'}];
const groups = groupBy(products, 'category');
const html = Object.keys(groups).reduce((code, cat) => {
const inner = groups[cat].reduce((i, product) => {
return i + `<p>${product.name}</p>`;
}, '');
return code + `<div><h2>${cat}</h2>${inner}</div>`;
}, '');
document.getElementById('container').innerHTML = html;
p { margin-left: 20px; }
<div id="container"></div>
var groupBy = function (xs, key) {
return xs.reduce(function (rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
const arrayData = [
{ id: 1, name: 'Apple', category: 'Fruit' },
{ id: 2, name: 'Melon', category: 'Fruit' },
{ id: 3, name: 'iPhone', category: 'Phone' },
{ id: 4, name: 'Samsung Galaxy Note 8', category: 'Phone' },
{ id: 5, name: 'Playstation 5', category: 'Entertainment' }
]
console.log(groupBy(arrayData, 'category'));
result:
{
"Fruit": [
{
"id": 1,
"name": "Apple",
"category": "Fruit"
},
{
"id": 2,
"name": "Melon",
"category": "Fruit"
}
],
"Phone": [
{
"id": 3,
"name": "iPhone",
"category": "Phone"
},
{
"id": 4,
"name": "Samsung Galaxy Note 8",
"category": "Phone"
}
],
"Entertainment": [
{
"id": 5,
"name": "Playstation 5",
"category": "Entertainment"
}
]
}

add qty for similar json objects in javascript

I want the result to be summing all the qty of same cat.
var data = [
{ cat: 'EK-1',name:"test",info:"mat", quantity: 3},
{ cat: 'EK-2', name:"test2",info:"nat"quantity: 1}
];
I tried like this below i have array of object having some similar objects. how to add qty and create unque objects .below i have given what i tried.
var data = [{
cat: 'EK-1',
name: "test",
info: "mat",
quantity: 1
},
{
cat: 'EK-1',
name: "test",
info: "mat",
quantity: 1
},
{
cat: 'EK-1',
name: "test",
info: "mat",
quantity: 1
},
{
cat: 'EK-2',
name: "test2",
info: "nat",
quantity: 1
}
];
const products = Array.from(data.reduce((acc, {
cat,
quantity
}) =>
acc.set(cat, (acc.get(cat) || 0) + quantity),
new Map()
), ([cat, quantity]) => ({
cat,
quantity
}));
console.log(products);
You can do this using Array#reduce, using the accumulator to pass on the new object:
var data = [ { cat: "EK-1", name: "test", info: "mat", quantity: 1, }, { cat: "EK-1", name: "test", info: "mat", quantity: 1, }, { cat: "EK-1", name: "test", info: "mat", quantity: 1, }, { cat: "EK-2", name: "test2", info: "nat", quantity: 1, }, ];
let seen = [];
const res = data.reduce((acc, { cat, ...rest }) => {
const idx = seen.indexOf(cat);
if (idx == -1) (acc.push({cat, ...rest}), seen.push(cat));
else acc[idx].quantity++;
return acc;
}, []);
console.log(res);

Merge item in array of object with the same ID on Javascript

this is how the object look:
let data = [
{
brandId: '12345',
brand: 'Adidas',
item: {
name: 'Adidas 1',
price: '200',
},
},
{
brandId: '12345',
brand: 'Adidas',
item: {
name: 'Adidas 2',
price: '230',
},
},
{
brandId: '7878',
brand: 'Nike',
item: {
name: 'Nike 1',
price: '305',
},
}
];
i want the item object will merge if the object have the same brandID :
let data = [
{
brandId: '12345',
brand: 'Adidas',
item: [
{
name: 'Adidas 1',
price: '200',
},
{
name: 'Adidas 2',
price: '230',
},
],
},
{
brandId: '7878',
brand: 'Nike',
item: {
name: 'Nike 2',
price: '316',
},
},
];
is there any javascript syntax or method to do this ? and with an explanation will be very nice, Thank You
(Assuming that your output is just a typo and name/price doesn't actually changes) You can use array reduce
let data = [
{
brandId: '12345',
brand: 'Adidas',
item: {
name: 'Adidas 1',
price: '200',
},
},
{
brandId: '12345',
brand: 'Adidas',
item: {
name: 'Adidas 2',
price: '230',
},
},
{
brandId: '7878',
brand: 'Nike',
item: {
name: 'Nike 1',
price: '305',
},
}
];
const mergedItems = data.reduce((acc, curr) => {
// check if current exist on the accumulator
const exist = acc.find(brand => brand.brandId === curr.brandId);
// if it does, add the item on it
if (exist) {
return acc.map((brand) => {
if (brand.brandId === exist.brandId) {
return {
...brand,
item: brand.item.concat(curr.item),
}
}
})
}
// if it doesnt, add it on accumulator, and make the item array
return acc.concat({
...curr,
item: [
curr.item
]
})
})
(I wrote the code manually and not tested)
You can simply achieve this result using Map
let data = [
{
brandId: "12345",
brand: "Adidas",
item: {
name: "Adidas 1",
price: "200",
},
},
{
brandId: "12345",
brand: "Adidas",
item: {
name: "Adidas 2",
price: "230",
},
},
{
brandId: "7878",
brand: "Nike",
item: {
name: "Nike 1",
price: "305",
},
},
];
const dict = new Map();
data.forEach((o) => {
dict.get(o.brandId)
? dict.get(o.brandId).item.push(o.item)
: dict.set(o.brandId, { ...o, item: [o.item] });
});
const result = [];
for (let [k, v] of dict) {
v.item.length === 1 ? result.push({ ...v, item: v.item[0] }) : result.push(v);
}
console.log(result);
/* This is not a part of answer. It is just to give the output fill height. So IGNORE IT */
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to create a nested array of object from an array of objects

How Can I loop through this array of objects and change it so that the individual menu items are nested in the object menu_name?
const menus = [
{ menu_name: 'Entre', id:0 },
{
name: 'Soup',
price: 14.99,
id:1
},
{
name: 'Chips & Salsa',
price: 7.99,
id:2
},
{
name: 'Chicken Nuggets',
price: 12.99,
id:3
},
{ menu_name: 'Sides', id:4 },
{
name: 'Fries',
price: 4.99,
id:5
},
{
name: 'Drinks',
price: 2.99,
id:6
},
{
name: 'Onion Rings',
price: 5.99,
id:7
},
];
the end result should look like this for each menu_name object, where an array of menus is nested in the menu_name object
{
menu_name: 'Sides',
menu: [
{
name: 'Fries',
price: 4.99,
},
{
name: 'Drinks',
price: 2.99,
},
{
name: 'Onion Rings',
price: 5.99,
},
],
},
You can easily achieve this using reduce and object destructuring
const menus = [
{ menu_name: "Entre", id: 0 },
{
name: "Soup",
price: 14.99,
id: 1,
},
{
name: "Chips & Salsa",
price: 7.99,
id: 2,
},
{
name: "Chicken Nuggets",
price: 12.99,
id: 3,
},
{ menu_name: "Sides", id: 4 },
{
name: "Fries",
price: 4.99,
id: 5,
},
{
name: "Drinks",
price: 2.99,
id: 6,
},
{
name: "Onion Rings",
price: 5.99,
id: 7,
},
];
const result = menus.reduce((acc, curr) => {
const { menu_name } = curr;
if (menu_name) {
acc.push({ menu_name, menu: [] });
} else {
const { name, price } = curr;
acc[acc.length - 1].menu.push({ name, price });
}
return acc;
}, []);
console.log(result);
var newMenu = [];
menus.forEach(menu=>{
if(menu.menu_name){
newMenu.push({...menu, menu: []})
}else{
newMenu[newMenu.length-1].menu.push(menu)
}
});

JavaScript Array Filtering and Mapping Problem. How to do nesting filtering?

Suppose, I have an array.
const arr = [
{
category: 'Diner',
item: [
{name: 'Chicken Rice', price: 200},
{name: 'Mutton Rice', price: 300},
],
},
{
category: 'Breakfast',
item: [
{name: 'Tea Bisuit', price: 100},
{name: 'Bread Butter', price: 300},
{name: 'Green Tea', price: 80},
],
},
];
How can I filter the array according to the item name?
For example, how can I filter the array with the item name Green Tea?
Output must be like this:
arr = [
{
category: 'Breakfast',
item: [
{name: 'Green Tea', price: 80},
],
},
];
You could map through arr, with each element, filter item to which match the term
After that, filter the arr again to reject the elements whose item is empty
const arr = [ { category: "Diner", item: [ { name: "Chicken Rice", price: 200 }, { name: "Mutton Rice", price: 300 }, ], }, { category: "Breakfast", item: [ { name: "Tea Bisuit", price: 100 }, { name: "Bread Butter", price: 300 }, { name: "Green Tea", price: 80 }, ], }, ]
const term = "Green Tea"
const res = arr
.map((categoryAndItems) => ({
category: categoryAndItems.category,
item: categoryAndItems.item.filter((item) => item.name === term),
}))
.filter((categoryAndItems) => categoryAndItems.item.length > 0)
console.log(res)

Categories