Given the following array:
var arr = [ { id: '123', numbers: [123,456,789] }, { id: '456', numbers: [6543,344,34534] }]
How can I get the parent object of the object containing 123 in the numbers array.
Eg. I want to search '123' and get:
{ id: '123', numbers: [123,456,789] }
I've tried using:
https://lodash.com/docs#find
_.find(arr, 123);
_.findKey(arr,123);
Can this be done with _map?
https://lodash.com/docs#map
Since you are already using lodash, you can use collection.find.
Syntax:
_.find(collection, [predicate=_.identity], [fromIndex=0])
[predicate=_.identity] is a function that is executed for every iteration. So instead of passing 123, pass this function.
Note: This can be done using Array functions, but they have compatibility issues and since you are already using lodash, in my understanding, this approach would suit better.
var arr = [{
id: '123',
numbers: [123, 456, 789]
}, {
id: '456',
numbers: [6543, 344, 34534]
}]
// ES6 version
var r = _.find(arr, x => x.id == '123');
// ES5 version
var r1 = _.find(arr, function(el){ return el.id == '123' });
console.log(r, r1)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.min.js"></script>
#gcampbell is correct.
Translate to JavaScript, it should be
_.find(arr, function(x) {
return x.numbers.includes(123);
});
You can refer to the Underscore documentation for further information.
Related
I have read several solutions to this problem here. When I try it, I continue to receive an error for the pop() method.
I have what is essentially a multidimensional array in javascript.
I am tasked with returning the array with the sensitive info removed (e.g. remove the SSN, in this example)
I thought I could use a foreach loop, and the pop() function to remove the last element of the child arrays, the SSN.
testing it using node on the commandline, the stdout is telling me that element.pop() is not a function. i've tried it with pop(), slice(), filter(), all with no success.
when running $> node filename.js
H:\Apache2\htdocs\test\filename.js:50
noppi[i] = element.pop();
^
TypeError: element.pop is not a function
let recs = [
{
ID: 1,
NAME: 'John',
EMAIL: 'john#example.com',
SSN: '123'
}, {
ID: 2,
NAME: 'Sally',
EMAIL: 'sally#example.com',
SSN: '456'
}, {
ID: 3,
NAME: 'Angie',
EMAIL: 'angie#example.com',
SSN: '789'
}
];
let i = 0;
let noppi = [];
recs.forEach(element => {
noppi[i] = element.pop();
i++;
});
console.log(noppi);
At the risk of sounding redundant, I'll briefly reiterate what the earlier answers have already stated.
The input data structure isn't a multi-dimensional array [ [ ... ], [ ... ] ] , it's an array of objects [ {...}, {...} ]. So you can't use Array methods like .pop() on the objects {...}.
Here's a simple one-liner that uses .forEach() and delete.
recs.forEach(obj => delete obj.SSN)
delete is an operator with one purpose: to remove an object's property like for example SSN: '123-45-6789'. Simple and perfect.
Note, .forEach() mutates the array, meaning that it's the original data being changed (see Minja's comment).
let recs = [
{
ID: 1,
NAME: 'John',
EMAIL: 'john#example.com',
SSN: '123'
}, {
ID: 2,
NAME: 'Sally',
EMAIL: 'sally#example.com',
SSN: '456'
}, {
ID: 3,
NAME: 'Angie',
EMAIL: 'angie#example.com',
SSN: '789'
}
];
recs.forEach(obj => delete obj.SSN);
console.log(recs)
Try this:
recs.forEach(element => {
noppi.push = element;
});
You are trying to use pop() on an object not an array
As per your need you need to remove SSN from your object, try below code it should work for you.
recs.forEach(element => {
const { SSN, ...rest } = element;
noppi.push(rest);
});
Here we are removing SSN from object and rest will push in noppi.
explain the use of the arrow function inside the .map() method here.
let mFunc= function(fname, data) {
for (i in data.shop) { //iterating through the JSON data
if (data.shop[i].name == fname) {
let dataSv = data.shop[i];
// We found a match, display details
for (y in dataSv){
if (typeof dataSv[y][0] === 'object') {
dataSv[y] = dataSv[y].map(z => z.name) // explain me this part
}
alert(i + " : " + dataSv[y])
}
}
}
}
}
.map(z => z.name)
Is shorthand for:
.map(z => {
return z.name;
})
So when you are only going to write a single line inside your function, and that is a return statement, you can use this shorthand.
This is just converting array of objects to array of strings which will contain the name of each element.
If you write an expression after => in array function with it will return that expression.
Body of arrow function
Arrow functions can have either a concise body or the usual block body.
In a concise body, only an expression is specified, which becomes the implicit return value. In a block body, you must use an explicit return statement
dataSv[y] = dataSv[y].map(z => z.name)
Is equivalent to
dataSv[y] = dataSv[y].map(z => {
return z.name;
})
Check this example. It may make it clearer
dataSv = [
[
{name: 'one', id: 1},
{name: 'two', id: 2},
{name: 'three', id: 3}
],
[
{name: 'eleven', id: 11},
{name: 'twelve', id: 12},
{name: 'thirteen', id: 13}
],
[
{name: 'twenty-one', id: 21},
{name: 'twenty-two', id: 22},
{name: 'twenty-three', id: 23}
]
]
dataSv[0] = dataSv[0].map(z => z.name)
dataSv[1] = dataSv[1].map(z => z.name)
dataSv[2] = dataSv[2].map(z => z.name)
console.info(dataSv)
It will return simply the "name" property of each element of the array, instead of the original object.
Basically whatever the code on the right-hand side of the => evaluates to becomes the returned value for each array element that .map() iterates over.
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map for more info and a runnable demo you can play with
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.
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.
How to Filter a response object based on an array of whitelisted ids?
I've a working version but i don't like the nested forEach here and i wonder if there is a way to improve it?!
function WhitelistCtrl($scope) {
var visible = [];
var whitelist = [123, 456]; // items to be visible
var response = [{
id: 123,
name: 'my object #1'
}, {
id: 456,
name: 'my object #2'
}, {
id: 789,
name: 'my object #3'
}];
angular.forEach(whitelist, function (id) {
angular.forEach(response, function (item) {
if (id === item.id) {
visible.push(item);
}
});
});
}
Here is a JSFiddle to play with: http://jsfiddle.net/gearsdigital/rv6vq2L7/
I'm not much familiar with Anglar ForEeach but you can achive this using native javascript filter like bellow
visible = response.filter(function(item){
return (whitelist.indexOf(item.id) > -1);
})
DEMO
NOTE:- IE8 doesn't supports .filter.