This question already has answers here:
javascript filter array of objects
(8 answers)
Closed 7 years ago.
I have the following array of objects :
var objs = [{id: 1, name: 'foo', ...},
{id: 2, name: 'bar', ...},
{id: 3, name: 'baz', ...}];
and this variable :
var matcher = 'bar';
What is the easiest way to get the object that has the matcher equals to its name ?
Using this matcher the result should be :
{id: 2, name: 'bar', ...}
The easiest way is to use filter function
var objs = [{id: 1, name: 'foo'},
{id: 2, name: 'bar'},
{id: 3, name: 'baz'}];
var matcher = 'bar';
var result = objs.filter(function(obj) {
return obj.name === matcher;
});
console.log(result); // [{id: 2, name: 'bar'}]
console.log(result[0]); // {id: 2, name: 'bar'}
The easiest way is probably using a library which allows some higher level functions on objects, such as filter.
Such libraries are for example underscore and lodash, both reserving the _ sign for use, with which you'd write:
_(objs).filter(function(element){return element.name === matcher})[0];
(The filter function returns the elements of an array or objects for which the given filtering function returns true - in this case, you're checking whether the name equals your matcher. The return value is an array of these elements, hence the [0] part)
EDIT: I didn't notice you had an array to begin with, then you don't even need an external library, arrays by default have the filter method on them.
Related
I have two array:
for example:
arraySelectedItems = [{id: 1, name: "item1"}, {id: 2, name: "item2"}]
arraySavedItems = [{id: 1, name: "item1"}, {id: 2, name: "item2"}]
now I need to check if there is some item in arraySavedItems that is not present in arraySelectedItems, and in this case I'll go to populate another array called arrayDeletedItems.
If the two arrays have the same items I don't need to populate the arrayDeletedItems.
So I have tried with this code:
arraySavedItems.filter((itemSaved) => !arraySelectedItems.find((itemSel) => {
if (itemSaved.id !== itemSel.id) {
arrayDeletedItems.push(itemSaved)
}
}
))
So with this data:
arraySelectedItems = [{id: 1, name: "item1"}, {id: 2, name: "item2"}]
arraySavedItems = [{id: 1, name: "item1"}, {id: 2, name: "item2"}]
I'll expect that arrayDeletedItems will be:
arrayDeletedItems = []
Instead whit this data for example:
arraySelectedItems = [{id: 1, name: "item1"}]
arraySavedItems = [{id: 1, name: "item1"}, {id: 2, name: "item2"}]
I'll expect that arrayDeletedItems will be:
arrayDeletedItems = [{id: 2, name: "item2"}]
With my code I receive and arrayDeletedItems that has the all values:
arrayDeletedItems = [{id: 1, name: "item1"}, {id: 2, name: "item2"}]
Consider this generic function:
function difference(a, b, keyFn) {
let keys = new Set(a.map(keyFn))
return b.filter(obj => !keys.has(keyFn(obj)))
}
//
selectedItems = [{id: 1, name: "item1"}, {id:4}]
savedItems = [{id: 1, name: "item1"}, {id: 2, name: "item2"}, {id:3}, {id:4}]
result = difference(selectedItems, savedItems, obj => obj.id)
console.log(result)
You can use the .includes() method on an array to check whether a value is contained in it (see the documentation for more information).
Now we can just filter the array of saved items to find only ones that aren't contained by the selected items array.
arrayDeletedItems = arraySavedItems.filter((itemSaved) =>
!arraySelectedItems.includes(itemSaved)
)
As #owenizedd points out in the comments, this only works for primitive data types where a shallow equality check is sufficient. A more robust approach can be used with the .reduce() method and a custom equality check. For example, lodash's isEqual() does a deep comparison for equality. You would have to import the module for this. Unfortunately there is no native deep equality check in JavaScript currently (workarounds like JSON.stringify() to then compare the string representations have various downsides).
arrayDeletedItems = arraySavedItems.filter((itemSaved) =>
!arraySelectedItems.reduce((previous, current) =>
previous || _.isEqual(current, itemSaved)
)
)
Note that passing previous as the first argument to the 'or' operator (||) means we can benefit from lazy evaluation - once a hit has been found, the second half of the statement does not need to be evaluated any more.
To solve this problem, since we have id we can utilize it.
You need a key that is unique. so id commonly known will have unique value.
So my approach, find items that is not exist in B array but in A array, and find items that exist in B but not in A array.
This approach not be the fastest, but the findDiff is reusable.
const a = [....];
const b = [....];
const findDiff = (source, target) => {
return source.filter((sourceItem, index) => {
const isInTarget = target.findIndex(targetItem => targetItem.id === sourceItem.id)
return isInTarget === -1
})
}
const difference = findDiff(a,b).concat(findDiff(b,a)); //result
How can I get an array of all keys which contain certain substring from dictionary array in JS? I tried to use reduce and map and filter, but don't know how to use those for this particular problem...
Input
[{id: 0, hello: 1}, {id: 1, world: 2}, {id: 2, bye: 3}]
Expected output (Get all keys with substring 'l')
['hello', 'world']
The .reduce method is great for this.
Here, we get the keys for each object in the array, and if a key contains the desired substring, we push it to the array that is being returned from each iteration of reduce.
const input =[
{id: 0, hello: 1}, {id: 1, world: 2}, {id: 2, bye: 3}
];
console.log(getKeysWithSubstring(input, "l"));
function getKeysWithSubstring(arrayOfObjs, needle){
return arrayOfObjs.reduce( (previousLoopOutput, currentObj) => {
// Renaming the output array for clarity
const thisLoopOutput = previousLoopOutput;
Object.keys(currentObj).forEach(haystack => {
// It's possible that many keys in the same object will be pushed
if(haystack.includes(needle)){
thisLoopOutput.push(haystack);
}
});
return thisLoopOutput;
}, []); // First time through loop, `previousLoopOutput` argument will be `[]`
}
This question already has answers here:
From an array of objects, extract value of a property as array
(24 answers)
Closed 2 years ago.
0: {id: "7B5B201E-35AA-48A1-B919-002445319F8B", name: "Naman Sabarwal"}
1: {id: "EA6672BA-4F7A-4214-A37F-00716CE698C9", name: "me name"}
2: {id: "01F29920-9206-42DF-8151-00A6A080C501", name: "Nitesh Negi"}
I want to get a list such that the list contains only the name key values.
listOfNames = ['sonu singh','me name','harman jain']
How to get all the values of the key 'name'?
listOfNames = jsonValues.map(x=>x.name)
You can try as follow.
let data = [
{id: "7B5B201E-35AA-48A1-B919-002445319F8B", name: "Naman Sabarwal"},
{id: "EA6672BA-4F7A-4214-A37F-00716CE698C9", name: "me name"},
{id: "01F29920-9206-42DF-8151-00A6A080C501", name: "Nitesh Negi"}
]; // assume the data is in array
let result = data.map( d => d.name );
console.log(result);
if it is json object like
details = [{id:"",name:""},{id:"",name:""},{id:"",name:""}]
you can use map function like
function getnames(){
let names = []
details.map((detail)=>{
names.push({name:detail.name})
return names
}
to shorten this
let names = values.map(value=>return value.name)
I have two arrays like so
data = [{id: 1, name: apple},
{id: 2, name: mango},
{id: 3, name: grapes},
{id: 4, name: banana}]
data2 =[{id: 1, name: apple},
{id: 3, name grapes}]
My Expected result would be:
[{ id: 2, name: mango},
{id:4, name: banana}]
My code is
let finalData =[];
data.forEach(result => {
data2.find(datum => {
if(datum['id'] === result['id]{
finalData.push(result);
}
})
})
I am getting wrong result. What is the simplest code or library that I can use?
Your sample data doesn't make sense, but assuming you mean that all data items that have matching IDs also have matching names and also assuming you want a set of all items where the IDs are the same in the two sets of data, you could use a Set to keep track of which IDs are present in one array then filter the second array by those that have their IDs in the set:
const idsInFirst = new Set(data.map(d => d.id));
const intersection = data2.filter(d => idsInFirst.has(d.id));
The reason why an intermediate Set structure is used is because it allows O(1) lookups after a one-time scan, which is more efficient than repeatedly scanning the first array over and over.
If you meant to say you wanted a difference between data sets (items excluded from data that are in data2), you'd want to negate/inverse things a bit:
const idsToExclude = new Set(data2.map(d => d.id));
const difference = data.filter(d => !idsToExclude.has(d.id));
Edit
After your clarifying edit, it's that second block of code that you'll want.
I would say a good way to do that is filtering your longest array using a function that will validate if the object id is present in both arrays. Check this example:
const data = [
{id: 1, name: 'apple'},
{id: 2, name: 'mango'},
{id: 3, name: 'grapes'},
{id: 4, name: 'banana'}
]
const data2 =[
{id: 1, name: 'apple' },
{id: 3, name: 'grapes' }
]
const longest = data.length > data2.length ? data : data2;
const shortest = data.length <= data2.length ? data : data2;
const finalData = longest.filter( obj => !shortest.find( o => o.id === obj.id ) )
console.log(finalData)
Good luck!
I need to detect an object in an array with its Id.
My first array looks like that:
{ [id: 9, name: 'abc'], [id: 2, name 'def'], [id: 40, name: 'gh'] } (Id & name),
while that other array is:
{ [class: 'physics', Tid: 9], [class: 'computer science', Tid: 9], [class: 'Biology', Tid: 40] }.
I need to match the parameter "name" from the first array by its ID to its "class" (for example, "physics" relates to Tid=9 which is "abc" and "Biology" relates to Tid=40 which is "gh").
How can I elegantly do so without changing the way the data comes? (It comes from a database with ASP.NET web service in JSON)
You could use $http.get() which has success and error callback functions, which returns a promise object. Using this, you can setup a condition to map the id and get your desired result.
Something like this.
var myObject1 = {};
var myArray1 = [];
var myObject2 = {};
var myArray2 = [];
$http.get('json-file')
.success(function(data)) {
myObject1.myArray1 = data;
}
$http.get('json-file')
.success(function(data)) {
myObject2.myArray2 = data;
}
/* inside a loop if required */
if (myObject1.myArray1[index].id == myObject2.myArray2[index].Tid) {
/* perform logic */
}
This code would be present inside a service or a controller.
Haven't tested it so unsure of the syntax but promise objects are the way to go.
Hope this helps.
This returns an array of arrays. Each array in the array contains two objects matched by id === Tid. As far as I can tell that's what you want.
(Note that I think you provided broken sample arrays, I adjusted and scrambled the numbers around so you could see it work more clearly).
var arr1 = [ {id: 9, name: 'abc'}, {id: 2, name: 'def'}, {id: 40, name: 'gh'} ];
var arr2 = [ {class: 'physics', Tid: 2}, {class: 'computer science', Tid: 40}, {class: 'Biology', Tid: 9} ];
var arrFinal = arr1.map ( function ( d ) {
var matched = arr2.find ( function ( obj ) {
return obj.Tid === d.id;
} );
return [ d, matched ];
} );
If you iterate arrFinal you'll see it contains the matched objects.