I have an array like this
[{
Item: pen,
Color: blue,
Brand: cello
},{
Item: pen,
Color: red,
Brand: cello
},{
Item: pen,
Color: blue,
Brand: cello
}]
I want the result to be like
[{
Item: pen,
Brand: cello
}]
I need to remove one attribute "Color" from the array and get unique value. Could some one help me how to achieve this output?
you can keep a new empty array, iterate over the original array delete color key from each object and push it to new array if it is not already present in the new array.
var arr = [{Item: 'pen', Color: 'blue', Brand: 'cello'}, {Item: 'pen', Color: 'red', Brand: 'cello'}, {Item: 'pen', Color: 'blue', Brand: 'cello'}];
var newArr = [];
arr.forEach(x => {
delete x.Color
for(var i=0; i<newArr.length; i++)
if(newArr[i].Item === x.Item && newArr[i].Brand === x.Brand)
return;
newArr.push(x);
});
console.log(newArr);
You can use array#reduce and array#some. Use delete to remove Color property from object.
var arr = [{ Item: 'pen',Color: 'blue',Brand: 'cello'},{Item: 'pen',Color: 'red',Brand: 'cello'},{Item: 'pen',Color: 'blue',Brand: 'cello'}];
var uniq = arr.reduce(function(u, o1){
delete o1.Color;
var isExist = u.some(function(o2){
return o2.Item === o1.Item && o2.Brand === o1.Brand;
});
if(!isExist)
u.push(o1);
return u;
},[]);
console.log(uniq);
You can map over each object in the array and assign its values to a new object. This new object, can have the color key deleted and pushed to a different array.
var array = [{
Item: 'pen',
Color: 'blue',
Brand: 'cello'
},{
Item: 'pen',
Color: 'red',
Brand: 'cello'
},{
Item: 'pen',
Color: 'blue',
Brand: 'cello'
}];
const newArray = [];
array.map(obj => {
let newObject = Object.assign({}, obj);
delete newObject.Color;
if(newArray.length) {
newArray.map(newObj => {
if(newObj.Item !== newObject.item && newObj.Brand !== newObject.Brand) {
newArray.push(newObject);
}
});
} else {
newArray.push(newObject);
}
});
console.log(array);
console.log(newArray);
Related
Pretend that i have this output data:
const fixedObj = {
factory: 'QWERTY',
}
const flexibleObj = {
itemName: ['abc', 'xyz'],
quantity: ['1', '2'],
color: ['red', 'blue'],
price: ['20$', '30$'],
}
These 2 objects are from one big object but they have to be separated for knowing if the key has array or not. If the key holds the data which has array like flexibleObj then the final output should be like this:
{
factory: 'QWERTY',
itemName: 'abc',
quantity: '1',
color: 'red',
price: '20$'
},
{
factory: 'QWERTY',
itemName: 'xyz',
quantity: '2',
color: 'blue',
price: '30$'
}
My question is: is there any posible way to convert like this ?
You can iterate over the itemName array and use the current index to get the information from all the other arrays to build a new object.
const fixedObj={factory:"QWERTY"},flexibleObj={itemName:["abc","xyz"],quantity:["1","2"],color:["red","blue"],price:["20$","30$"]};
// Destructure the properties from the object
const {
itemName,
quantity,
color,
price
} = flexibleObj;
// Iterate over the itemName array and utilise
// the index to get the elements of the other
// arrays to build an object
const arr = itemName.map((item, i) => {
return {
factory: fixedObj.factory,
itemName: item,
quantity: quantity[i],
color: color[i],
price: price[i]
};
});
console.log(arr);
const fixedObj = {
factory: 'QWERTY',
}
const flexibleObj = {
itemName: ['abc', 'xyz'],
quantity: ['1', '2'],
color: ['red', 'blue'],
price: ['20$', '30$'],
}
const result = []
for (let i = 0; i < flexibleObj.itemName.length; i++) {
result.push({
...fixedObj,
itemName: flexibleObj.itemName[i],
quantity: flexibleObj.quantity[i],
color: flexibleObj.color[i],
price: flexibleObj.price[i],
})
}
console.log(result)
Here is a generic approach that takes care of all existing properties in flexibleObj and fixedObj:
const fixedObj={factory:"QWERTY", location:"Hanover"},flexibleObj={itemName:["abc","xyz"],quantity:["1","2"],color:["red","blue"],price:["20$","30$"],extra:[7,13]};
const flex=Object.entries(flexibleObj);
const arr = flex[0].map((_,i)=>{
const o = {...fixedObj};
flex.forEach(([k,ar])=>o[k]=ar[i]);
return o;
});
console.log(arr);
This question already has answers here:
Group array items using object
(19 answers)
Closed last year.
I have an array of objects and I would like to group the objects which have same name and make an array containing the other values which differs. How can I achieve that?
const arr = [
{
name: 'A',
color: 'blue',
},
{
name: 'A',
color: 'purple',
},
{
name: 'B',
color: 'Yellow',
},
{
name: 'B',
color: 'Green',
},
];
What I would like to get:
const result = [
{
name: 'A',
color: ['blue', 'purple'],
},
{
name: 'B',
color: ['Yellow', 'Green'],
},
];
This looks like something reduce() should be used for.
Use find() to find in the existing array element based on some condition.
If element exists, push into colors property of the element.
Else push into the array a new object.
const arr = [
{
name: 'A',
color: 'blue',
},
{
name: 'A',
color: 'purple',
},
{
name: 'B',
color: 'Yellow',
},
{
name: 'B',
color: 'Green',
},
];
let ans = arr.reduce((agg,curr) => {
let found = agg.find((x) => x.name === curr.name);
if(found){
found.colors.push(curr.color);
}
else{
agg.push({
name : curr.name,
colors : [curr.color]
});
}
return agg;
},[]);
console.log(ans);
const found = acc.find(item => item.name === curr.name);
if (found) {
found.color.push(curr.color);
} else {
acc.push({
name: curr.name,
color: [curr.color],
});
}
return acc;
}
, []);
Here is one way to do it:
const arrNames = Array.from(new Set(arr.map((x) => x.name))); // make an array of unique names
const result = arrNames
.map((x) => arr.filter((y) => y.name === x)) // filter by name
.map((x, i) => ({ name: arrNames[i], color: x.map((y) => y.color) })); // make new objects
Create set of props then loop over possible names and filter their values O(n^2)
const set = new Set(arr.map((obj) => obj.name));
const res = [];
for(const name of set.keys()) {
const colors = arr.filter((obj) => obj.name === name).map((obj) => obj.color);
res.push({name, colors});
}
Or create a dictionary whose keys will be name-s, and values - array O(n)
const mp = new Map();
for (const obj of arr) {
if (mp.has(obj.name)) {
mp.get(obj.name).push(obj.color);
} else {
mp.set(obj.name, [obj.color]);
}
}
const result = [];
for (const [name, color] of mp.entries()) {
result.push({name, color});
}
let results = [];
const arr = [
{
name: "A",
color: "blue",
},
{
name: "A",
color: "purple",
},
{
name: "B",
color: "Yellow",
},
{
name: "B",
color: "Green",
},
];
const names = arr.map((element) => element.name);
const uniqueNames = [...new Set(names)];
uniqueNames.forEach((element) => {
let temp = {};
temp.name = element;
temp.color = [];
arr.forEach((element2) => {
if (element === element2.name) {
temp.color.push(element2.color);
}
});
results.push(temp);
});
console.log("results", results);
I would like how to convert the object to array of objects in JavaScript.
In object obj, fields should be modified to nested array of objects in JavaScript.
var obj = [{
id: 1,
fields: {
color: "white",
brand: "xyz"
}
}]
function objarray(obj) {
return obj.map(e => ({
label: Object.keys(e.fields)
}))
}
var result = objarray(obj);
console.log(result);
Expected Output:
[
{
label: "color",
children: [{label:"white" }]
},
{
label: "brand",
children: [{label:"xyz" }]
}
]
Obj.map isn't going to work as obj is an array with one element so it will only iterate one time.
let newArray = []
for (var i in obj.fields)
{
newArray.push({label: i, children:obj[[0].fields.i});
}
I doubt this will compile. I suspect i is an object here and can't be used as a reference on obj[0].fields.
but You get the idea.
This should do the trick
var obj = [{
id: 1,
fields: {
color: "white",
brand: "xyz"
}
}]
const mapFields = (obj) => {
return obj.map((o) => {
return Object.keys(o.fields).map((f) => {
var field = {
label: f,
children: [{label: o.fields[f]}]
};
return field;
});
})
}
console.log(mapFields(obj));
You can do this by making use of Object.entries():
var obj = [ { id: 1, fields: { color: "white", brand: "xyz" } }];
result = Object.entries(obj[0].fields).map(([k,v])=>({label:k, children:[{label:v}]}))
console.log(result)
I have been toying with the best way to go about doing this and have found some options but not one that preserves the format I am trying to keep for the array/object.
The overview is I have an array that gets random objects pushed into it and there can be duplicates of the same object, but I want to change it so there is only 1 of each object and instead, having a count property for each object.
An example of what I am working with and what I am aiming to have.
arr = [
{ Name: Item1, Value: 20 },
{ Name: Item2, Value: 20 },
{ Name: Item1, Value: 20 }
];
result = [
{ Name: Item1, Value: 20, Count: 2 },
{ Name: Item2, Value: 20, Count: 1 }
];
As a side note, I am wondering if it better to do this after the array is filled or if it is better to do this while pushing the objects into the array?
Assuming the value of each item is the same, you can do a simple forEach loop. For each element, check to see if the object exists in 'result'. If so, increment the count, otherwise add it to the result array.
let result = [];
arr.forEach(item => {
let resObj = result.find(resObj => resObj.Name === item.Name);
resObj ? resObj.Count++ : result.push({'Name':item.Name, 'Value': item.Value, 'Count': 1});
});
console.log(result);
In this case, you don't want to use arr.map, since we're not updating the original array.
If items are continuously being added, you can maintain an "index" (by Name) of objects you've already added to the array so that whenever a new object is added, you can update the count if it's already present or push it to the array if it's not:
var arr = [];
var index = {};
function addItem(o) {
if (o.Name in index) {
index[o.Name].Count += 1;
} else {
index[o.Name] = o;
o.Count = 1;
arr.push(o);
}
}
addItem({
Name: 'Item1',
Value: 20
});
addItem({
Name: 'Item2',
Value: 20
});
addItem({
Name: 'Item1',
Value: 20
});
console.log(arr);
The benefit of this approach is that you don't have to recompute counts from scratch (which is an O(n) operation) every time you want to get the result array.
You can loop through the array and maintain 1 temporary object with "Name" as a key, If same name is found increment "count" by 1
let array = [{ Name: 'Item1', Value: 20 }, { Name: 'Item2', Value: 20 }, { Name: 'Item1', Value: 20 }]
let tempResult = {}
for (let d of array) {
tempResult[d.Name] = {
count: 1,
...d,
...(tempResult[d.Name] && { count: tempResult[d.Name].count + 1 })
}
}
let result = Object.values(tempResult)
console.log(result);
You could take a hash table and count same items.
var array = [{ Name: 'Item1', Value: 20 }, { Name: 'Item2', Value: 20 }, { Name: 'Item1', Value: 20 }],
result = Object.values(array.reduce((r, { Name, Value }) => {
r[Name] = r[Name] || { Name, Value, Count: 0 };
r[Name].Count++;
return r;
}, {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I am trying to add a reducer in redux that deletes multiple items in the state based on an array of values.
Say I have the array
const idArray = ["935", "933", "930"];
And I would like to delete the objects that have an id property that matches one of the values in the idArray and return a new array with the remaining values.
const objectsArray= [
{
name: "Kevin",
color: "red",
id: "935"
},
{
name: "Ana",
color: "white",
id: "815"
},
{
name: "Maria",
color: "silver",
id: "035"
},
{
name: "Victor",
color: "red",
id: "935"
},
{
name: "Vanessa",
color: "red",
id: "933"
},
]
So in this case, i would like to remove the objects that have the names: Kevin, Vanessa and Victor, and return a new array with Ana and Maria.
This is what i have in my reducer so far:
case PeopleActions.DELETE_PEOPLE:
if (action.id.length === 1) {
return state.filter(people =>
people.id !== action.id[0]
);
} else {
const deletePeople: any = () => {
for (let i = 0; i < action.id.length; i++) {
return state.filter(poeple =>
people.id !== action.id[i]
);
}
};
return deletePeople;
}
I presume since objectsArray is marked const then reassigning a new array is out, which means no filter().
If you need to mutate the array in place, the best option might be to simply loop through the array backwards and splice as you go:
const idArray = ["935", "933", "930"];
const objectsArray= [{ name: "Kevin", color: "red", id: "935"},{ name: "Ana", color: "white", id: "815"},{ name: "Maria", color: "silver", id: "035"},{ name: "Victor", color: "red", id: "935"},{ name: "Vanessa", color: "red", id: "933"},]
for (let i = objectsArray.length-1; i >=0 ; i--){
if(idArray.includes(objectsArray[i].id)){
objectsArray.splice(i,1);
}
}
console.log(objectsArray);