This question already has answers here:
How to filter object array based on attributes?
(21 answers)
Closed 4 years ago.
Sorry for my bad English. If I have an array:
const myobj = [
{
id: 1,
name: 'First...'
},
{
id: 2,
name: 'Second...
}];
How can I remove, for example, the object with id 2? To leave the array only with first object. Which functions should I use? Thanks in advance.
Found solution:
function removeByKey(array, params){
array.some(function(item, index) {
if(array[index][params.key] === params.value){
array.splice(index, 1);
return true;
}
return false;
});
return array;
}
Then
removeByKey(myobj, {
key: 'id',
value: 2
})
http://jsforallof.us/2015/07/08/remove-object-by-key-from-array/
Use Array.prototype.filter which produces new array based on the provided condition.
const myobj = [{ id: 1, name: 'First...' }, { id: 2, name: 'Second...' }];
console.log(myobj.filter(v => v.id !== 2));
Similarly you can use Array.prototype.reduce
const myobj = [{ id: 1, name: 'First...' }, { id: 2, name: 'Second...' }];
console.log(myobj.reduce((acc, v) => v.id !== 2 ? acc.concat(v) : acc, []));
Using filter and assuming myobj is not constant you can do the following:
myobj = [
{
id: 1,
name: 'First...'
},
{
id: 2,
name: 'Second...'
},
{
id: 3,
name: 'Third...'
}
];
myobj = myobj.filter(v => v.id !== 2);
console.log(myobj);
first, you have an array, not an object in myobj, one way of many you could do this is to remove the item by filtering:
const myFilteredArray = myobj.filter(i => i.id !== 2);
See the javascript filter function
Related
I've tried modifying some of the similar solutions on here but I keep getting stuck, I believe I have part of this figured out however, the main caveat is that:
Some of the objects have extra keys, which renders my object comparison logic useless.
I am trying to compare two arrays of objects. One array is the original array, and the other array contains the items I want deleted from the original array. However there's one extra issue in that the second array contains extra keys, so my comparison logic doesn't work.
An example would make this easier, let's say I have the following two arrays:
const originalArray = [{id: 1, name: "darnell"}, {id: 2, name: "funboi"},
{id: 3, name: "jackson5"}, {id: 4, name: "zelensky"}];
const itemsToBeRemoved = [{id: 2, name: "funboi", extraProperty: "something"},
{id: 4, name: "zelensky", extraProperty: "somethingelse"}];
after running the logic, my final output should be this array:
[{id: 1, name: "darnell"}, {id: 3, name: "jackson5"}]
And here's the current code / logic that I have, which compares but doesn't handle the extra keys. How should I handle this? Thank you in advance.
const prepareArray = (arr) => {
return arr.map((el) => {
if (typeof el === "object" && el !== null) {
return JSON.stringify(el);
} else {
return el;
}
});
};
const convertJSON = (arr) => {
return arr.map((el) => {
return JSON.parse(el);
});
};
const compareArrays = (arr1, arr2) => {
const currentArray = [...prepareArray(arr1)];
const deletedItems = [...prepareArray(arr2)];
const compared = currentArray.filter((el) => deletedItems.indexOf(el) === -1);
return convertJSON(compared);
};
How about using filter and some? You can extend the filter condition on select properties using &&.
const originalArray = [
{ id: 1, name: 'darnell' },
{ id: 2, name: 'funboi' },
{ id: 3, name: 'jackson5' },
{ id: 4, name: 'zelensky' },
];
const itemsToBeRemoved = [
{ id: 2, name: 'funboi', extraProperty: 'something' },
{ id: 4, name: 'zelensky', extraProperty: 'somethingelse' },
];
console.log(
originalArray.filter(item => !itemsToBeRemoved.some(itemToBeRemoved => itemToBeRemoved.id === item.id))
)
Or you can generalise it as well.
const originalArray = [
{ id: 1, name: 'darnell' },
{ id: 2, name: 'funboi' },
{ id: 3, name: 'jackson5' },
{ id: 4, name: 'zelensky' },
];
const itemsToBeRemoved = [
{ id: 2, name: 'funboi', extraProperty: 'something' },
{ id: 4, name: 'zelensky', extraProperty: 'somethingelse' },
];
function filterIfSubset(originalArray, itemsToBeRemoved) {
const filteredArray = [];
for (let i = 0; i < originalArray.length; i++) {
let isSubset = false;
for (let j = 0; j < itemsToBeRemoved.length; j++) {
// check if whole object is a subset of the object in itemsToBeRemoved
if (Object.keys(originalArray[i]).every(key => originalArray[i][key] === itemsToBeRemoved[j][key])) {
isSubset = true;
}
}
if (!isSubset) {
filteredArray.push(originalArray[i]);
}
}
return filteredArray;
}
console.log(filterIfSubset(originalArray, itemsToBeRemoved));
Another simpler variation of the second approach:
const originalArray = [
{ id: 1, name: 'darnell' },
{ id: 2, name: 'funboi' },
{ id: 3, name: 'jackson5' },
{ id: 4, name: 'zelensky' },
];
const itemsToBeRemoved = [
{ id: 2, name: 'funboi', extraProperty: 'something' },
{ id: 4, name: 'zelensky', extraProperty: 'somethingelse' },
];
const removeSubsetObjectsIfExists = (originalArray, itemsToBeRemoved) => {
return originalArray.filter(item => {
const isSubset = itemsToBeRemoved.some(itemToBeRemoved => {
return Object.keys(item).every(key => {
return item[key] === itemToBeRemoved[key];
});
});
return !isSubset;
});
}
console.log(removeSubsetObjectsIfExists(originalArray, itemsToBeRemoved));
The example below is a reusable function, the third parameter is the key to which you compare values from both arrays.
Details are commented in example
const arr=[{id:1,name:"darnell"},{id:2,name:"funboi"},{id:3,name:"jackson5"},{id:4,name:"zelensky"}],del=[{id:2,name:"funboi",extraProperty:"something"},{id:4,name:"zelensky",extraProperty:"somethingelse"}];
/** Compare arrayA vs. delArray by a given key's value.
--- ex. key = 'id'
**/
function deleteByKey(arrayA, delArray, key) {
/* Get an array of only the values of the given key from delArray
--- ex. delList = [1, 2, 3, 4]
*/
const delList = delArray.map(obj => obj[key]);
/* On every object of arrayA compare delList values vs
current object's key's value
--- ex. current obj[id] = 2
--- [1, 2, 3, 4].includes(obj[id])
Any match returns an empty array and non-matches are returned
in it's own array.
--- ex. ? [] : [obj]
The final return is a flattened array of the non-matching objects
*/
return arrayA.flatMap(obj => delList.includes(obj[key]) ? [] : [obj]);
};
console.log(deleteByKey(arr, del, 'id'));
let ff = [{ id: 1, name: 'darnell' }, { id: 2, name: 'funboi' },
{ id: 3, name: 'jackson5' },
{ id: 4, name: 'zelensky' }]
let cc = [{ id: 2, name: 'funboi', extraProperty: 'something' },
{ id: 4, name: 'zelensky', extraProperty: 'somethingelse' }]
let ar = []
let out = []
const result = ff.filter(function(i){
ar.push(i.id)
cc.forEach(function(k){
out.push(k.id)
})
if(!out.includes(i.id)){
// console.log(i.id, i)
return i
}
})
console.log(result)
This question already has answers here:
How to find object in array by property in javascript?
(3 answers)
Closed 2 years ago.
I have 2 Array:
const arr1 = [
{
id: 1,
name: "a"
},
{
id: 2,
name: "ab"
},
{
id: 3,
name: "abc"
}]
and
const arr2 = [{id:"1"}, {id:"3"}]
How can i get from two above array to get the result like that:
const result = ["a", "abc"]
I'm struggling with array built-in function. Thank you for reading.
You could do something like the following.
const arr1 = [{ id: 1, name: "a"}, {id: 2, name: "ab"}, { id: 3, name: "abc" }]
const arr2 = [{ id: 1 }, { id: 3 }];
const ids = arr2.map(item => item.id);
const includedIds = arr1.filter(item => ids.includes(item.id)).map(item => item.id)
console.log(includedIds)
I have array of array of object as follows:
[
[
{
id: 1,
itemName: 'xxx',
...
},
{
id: 1,
itemName: 'yyy',
...
},
...
],
[
{
id: 2,
itemName: 'aaa',
...
},
{
id: 2,
itemName: 'kkk',
...
},
...
],
[
{
id: 3,
itemName: 'kkk',
...
},
{
id: 3,
itemName: 'yyy',
...
},
...
]
]
I am trying to check if any itemName from objects inside arrays equals given string, but I stuck at the solution that keeps these arrays with such object in one array. Here is my solution:
function isNameAcrossData(givenString){
return arr.map(arrItem =>
arrItem.find(item => item.itemId === givenString)
);
}
My solution doesn't return boolean but just one array with objects, that contain givenString and undefined as last array element. How to modify it to return just true/false value?
Use a .some inside a .some, to see if some of the arrays have at least one element inside matching the condition:
const isNameAcrossData = givenString => arr.some(
subarr => subarr.some(
({ itemName }) => itemName === givenString
)
);
const arr=[[{id:1,itemName:"xxx"},{id:1,itemName:"yyy"}],[{id:2,itemName:"aaa"},{id:2,itemName:"kkk"}],[{id:3,itemName:"kkk"},{id:3,itemName:"yyy"}]];
console.log(isNameAcrossData('xxx'));
console.log(isNameAcrossData('doesntexist'));
You could also flatten the outer array first:
const isNameAcrossData = givenString => arr.flat().some(
({ itemName }) => itemName === givenString
);
const arr=[[{id:1,itemName:"xxx"},{id:1,itemName:"yyy"}],[{id:2,itemName:"aaa"},{id:2,itemName:"kkk"}],[{id:3,itemName:"kkk"},{id:3,itemName:"yyy"}]];
console.log(isNameAcrossData('xxx'));
console.log(isNameAcrossData('doesntexist'));
You could check with some and return an array of boolean with using the wanted property.
function mapHasValue(key, value) {
return data.map(array => array.some(item => item[key] === value));
}
var data = [[{ id: 1, itemName: 'xxx' }, { id: 1, itemName: 'yyy' }], [{ id: 2, itemName: 'aaa' }, { id: 2, itemName: 'kkk' }], [{ id: 3, itemName: 'kkk' }, { id: 3, itemName: 'yyy' }]];
console.log(mapHasValue('id', 3));
Your code returns
[undefined, undefined, undefined]
because map returns an array so this approach won't work
You have first to loop through all the data and check inside then outside the loop assign to some variable true if there is a match.
Basically you have to return after you loop the data.
Working example for both cases:
const arr=[[{id:1,itemName:"xxx"},{id:1,itemName:"yyy"}],[{id:2,itemName:"aaa"},{id:2,itemName:"kkk"}],[{id:3,itemName:"kkk"},{id:3,itemName:"yyy"}]];
function isNameAcrossData(givenString){
let isMatch = false;
arr.map(childArr => {
childArr.map(obj => obj.itemName === givenString ? isMatch = true : null);
});
return isMatch;
}
console.log(isNameAcrossData('kkk'));
console.log(isNameAcrossData('bbb'));
This question already has answers here:
Sum of same object name in javascript
(4 answers)
Want to sum of values with same property name in object using javascript or jquery [closed]
(2 answers)
What is a efficient way to condense a List of objects to based on an object value?
(2 answers)
Reduce an Array of object based on value of attribute
(5 answers)
Closed 4 years ago.
I have something like this:
tires: [{
name: "fancyProduct1",
quantity: 1
}, {
name: "fancyProduct1",
quantity: 1
}, {
name: "fancyProduct1",
quantity: 1
}, {
name: "fancyProduct2",
quantity: 1
}];
What I'm trying to accomplish is
tires: [{
name: "fancyProduct1",
quantity: 3
}, {
name: "fancyProduct2",
quantity: 1
}]
Any ideas on best way to approach this?
You can use reduce to group the array into one object. Use Object.values to convert the object into an array.
let tires = [{"name":"fancyProduct1","quantity":1},{"name":"fancyProduct1","quantity":1},{"name":"fancyProduct1","quantity":1},{"name":"fancyProduct2","quantity":1}];
let result = Object.values(tires.reduce((c, {name,quantity}) => {
c[name] = c[name] || {name,quantity: 0}
c[name].quantity += quantity;
return c;
}, {}));
console.log(result);
Using Reduce will accomplish this:
var products = { tires: [ {name: "fancyProduct1", quantity: 1}, {name: "fancyProduct1", quantity: 1}, {name: "fancyProduct1", quantity: 1}, {name: "fancyProduct2", quantity: 1}] };
var result = products.tires.reduce((acc,current) => {
if (!acc[current.name]) {
acc[current.name] = { name: current.name, quantity: 0};
}
acc[current.name].quantity++;
return acc;
}, {});
var resultArray = Object.values(result);
console.log(resultArray);
Well you can use a simple Array.forEach() call to loop over the array items, along with Array.find() to check for the existence of your iterated item in the result array and do your logic accordingly.
This is how should be your code:
var result = [];
tires.forEach(function(el) {
let found = result.find(o => o.name === el.name);
if (found) {
found["quantity"] += el["quantity"];
} else {
result.push(el);
}
});
Demo:
var tires = [{
name: "fancyProduct1",
quantity: 1
}, {
name: "fancyProduct1",
quantity: 1
}, {
name: "fancyProduct1",
quantity: 1
}, {
name: "fancyProduct2",
quantity: 1
}];
var result = [];
tires.forEach(function(el) {
let found = result.find(o => o.name === el.name);
if (found) {
found["quantity"] += el["quantity"];
} else {
result.push(el);
}
});
console.log(result);
You can do something like this...
var newTries = tires.map(n => (
// logic for new array where you can get attributes of item in tires to create a new array.
console.log(n); // this can show what properties are available in the current item write it to the console.
)};
Hope this helps.
I have the following two Javascript arrays:
const array1 = [{ id: 1}, { id: 2 }, { id: 3 }, { id: 4}];
const array2 = [{ id: 1}, { id: 3 }];
I now want a new array array3 that contains only the objects that aren't already in array2, so:
const array3 = [{ id: 2}, { id: 4 }];
I have tried the following but it returns all objects, and when I changed the condition to === it returns the objects of array2.
const array3 = array1.filter(entry1 => {
return array2.some(entry2 => entry1.id !== entry2.id);
});
Any idea? ES6 welcome
You could reverse the comparison (equal instead of unqual) and return the negated result of some.
const
array1 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }],
array2 = [{ id: 1 }, { id: 3 }],
array3 = array1.filter(entry1 => !array2.some(entry2 => entry1.id === entry2.id));
// ^ ^^^
console.log(array3);
Nina's answer is a good start but will miss any unique elements in array 2.
This extends her answer to get the unique elements from each array and then combine them:
const
array1 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }],
array2 = [{ id: 1 }, { id: 3 }, { id: 5 }],
array3 = array1.filter(entry1 => !array2.some(entry2 => entry1.id === entry2.id)),
array4 = array2.filter(entry1 => !array1.some(entry2 => entry1.id === entry2.id)),
array5 = array3.concat(array4);
console.log(array5);