how to use lodash to find specific result in collection? - javascript

I am working on lodash ...I want to find particular array if matching id mind in that particular array...This is my collection:-
[ { name: 'Thor',
id:
[ '5a1676da509a93571c15501f',
'59ffb40f62d346204e09c9ad',
'5a0a92e01bb28a276abfa548' ] },
{ name: 'Loki',
id:
[ '59ffb40f62d346204e09c9ad',
'59ffb41b62d346204e0a03ed',
'59ffb40e62d346204e09c298',
'5a65853af431924e73c401fe' ] } ]
What I am trying to find i have given id if it should find it above collection then it should return that collection...for example..if i have id:59ffb40e62d346204e09c298,then it should return 2 collection.....
b = _.find(upperArray,(candidate) => {
// console.log(candidate)
return _.find(candidate.id,id)//here actor_id is given id
})
but it does not return 2 collection.If it does not found any matching element it should return blank array or if found it should return collection of array.Where I am doing wrong??

#Barmar is correct you should use _.filter. Try the following
var upperArray = [
{
name: 'Thor',
id: [
'5a1676da509a93571c15501f',
'59ffb40f62d346204e09c9ad',
'5a0a92e01bb28a276abfa548'
]
},
{
name: 'Loki',
id: [
'59ffb40f62d346204e09c9ad',
'59ffb41b62d346204e0a03ed',
'59ffb40e62d346204e09c298',
'5a65853af431924e73c401fe'
]
}
];
function findById(idToFind) {
return _.filter(upperArray,function(candidate) {
return _.includes(candidate.id, idToFind);
});
}
var b = findById('59ffb40e62d346204e09c298');
console.log(b);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

Using can achieve the same using native array methods
var id = "59ffb40e62d346204e09c298";
var arr = [{
name: 'Thor',
id: ['5a1676da509a93571c15501f',
'59ffb40f62d346204e09c9ad',
'5a0a92e01bb28a276abfa548'
]
},
{
name: 'Loki',
id: ['59ffb40f62d346204e09c9ad',
'59ffb41b62d346204e0a03ed',
'59ffb40e62d346204e09c298',
'5a65853af431924e73c401fe'
]
}
]
function getMatchedCollection(id) {
// filter will return a new array of matched condition
return arr.filter(function(item) {
// indexOf is used to check if an element is present
if (item.id.indexOf(id) !== -1) {
return item
}
})
}
console.log(getMatchedCollection(id))

Related

Using indexOf in order to filt an array - ( Next.js app with typescript )

I have this array in my next.js app
arr1
[
{
identifier: "60a17722225f2918c445fd19",
name: "Ben Awad",
_id: "60c94480b8d43c28d0a6eb73
},
{
identifier: "60a455d11fa62a1510b408f8",
name: "dev ed"
_id: "60bf62cede309f1a30fe88ab"
}
]
And i have this another big array
arr2
[
{
name: "Ben Awad",
_id: "60a17722225f2918c445fd19
},
{
name: "dev ed",
_id: "60a455d11fa62a1510b408f8"
},
{
name: "Katlyn",
_id: "60a52500ce96f30c14fdaff9"
},
{
name: "Mike",
_id: "60c95deeb8d43c28d0a6eb74"
},
{
name: "Kassandra",
_id: "60c960ddb8d43c28d0a6eb7a"
}
]
I want a new array who should have all users except for those who have similar ids with arr1
So this is the logic i did (Notice that arr1 and arr2 will change constantly)
Me = arr1
AllUsers = arr2
const LookFriends =
Me &&
AllUsers.filter(({ _id }) => {
return Me.friends.indexOf(_id) === -1;
});
console.log(LookFriends);
The output should be Katlyn, Mike and Kassandra, but the console.log says...
[
{
name: "Ben Awad",
_id: "60a17722225f2918c445fd19
},
{
name: "dev ed",
_id: "60a455d11fa62a1510b408f8"
},
{
name: "Katlyn",
_id: "60a52500ce96f30c14fdaff9"
},
{
name: "Mike",
_id: "60c95deeb8d43c28d0a6eb74"
},
{
name: "Kassandra",
_id: "60c960ddb8d43c28d0a6eb7a"
}
]
I'm really having a hard time trying to filter an array based on another array, what can i do ?
You need to use 'findIndex' in this case, then compare the _id field itself:
const LookFriends =
Me &&
AllUsers.filter(({ _id }) => {
return Me.friends.findIndex(friend => friend._id === _id) === -1;
});
If you use "indexOf", it will compare the entire object to just that _id value.
You can extract the identifiers from the first array and filter the second array if the element doesn't match any id in our object or our Set
// with an object
const ids = {}
arr1.forEach(user => {
ids[user.identifier] = true
})
const filtered = arr2.filter(user => !ids[user._id])
// or with a Set
const ids = new Set(arr1.map(user => user.identifier))
const filtered = arr2.filter(user => !ids.has(user._id))
Please have a try with this code.
Me &&
AllUsers.filter(({ _id }) => {
let bExist = false
Me.friends.map( (friend) => {
if ( friend._id === _id )
bExist = true
})
return bExist
});
Let me know if it works or not.

lodash filter not finding value in multidimensional array of Shopify order

Looking to see if an order line_item has been refunded before processing...
Here is a single order:
var order = {
line_items: [
{
id: 1326167752753
}
],
refunds: [
{
refund_line_items: [
{
id: 41264152625,
line_item_id: 1326167752753,
}
]
}
]
};
Trying to log out the filter results:
console.log(
_.filter(order, {
refunds: [
{
refund_line_items: [
{
line_item_id: 1326167752753
}
]
}
]
}).length
);
I'm getting 0 on the console.
Am I using _.filter wrong in this case?
Function take needs an array (order is not an array, order.refunds is) and a predicate, not an object.
Anyway, I'd write it using Array.some:
const itemWasRefunded = order.refunds.some(refund =>
refund.refund_line_items.some(refund_line_item =>
refund_line_item.line_item_id === 1326167752753
)
);
Or, alternatively, getting all line_item_ids and checking inclusion:
const itemWasRefunded = _(order.refunds)
.flatMap("refund_line_items")
.map("line_item_id")
.includes(1326167752753);
You can use some and find and do this in lodash and also easily in ES6:
var order = { line_items: [{ id: 1326167752753 }], refunds: [{ refund_line_items: [{ id: 41264152625, line_item_id: 1326167752753, }] }] };
// lodash
const _searchRefunds = (lid) => _.some(order.refunds, x =>
_.find(x.refund_line_items, {line_item_id: lid}))
console.log('loadsh:', _searchRefunds(1326167752753)) // true
console.log('loadsh:', _searchRefunds(132616772323232352753)) // false
//es6
const searchRefunds = (lid) => order.refunds.some(x =>
x.refund_line_items.find(y => y.line_item_id == lid))
console.log('ES6:', searchRefunds(1326167752753)) // true
console.log('ES6:', searchRefunds(132616772323232352753)) // false
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Find duplicate values by key from array of objects in Javascript

I know this question was answered before multiple times.
but i didn't find any solution that helped me out.
I got an array of objects with a Name property. I only want to get the objects with the same name.
How my Array looks like:
[
{
Name: 'test',
coolProperty: 'yeahCool1'
},
{
Name: 'test1',
coolProperty: 'yeahCool2'
},
{
Name: 'test2',
coolProperty: 'yeahCool3'
},
{
Name: 'test3',
coolProperty: 'yeahCool4'
},
{
Name: 'test',
coolProperty: 'yeahCool5'
}
]
so I only want to get:
[
{
Name: 'test',
coolProperty: 'yeahCool1'
},
{
Name: 'test',
coolProperty: 'yeahCool5'
}
]
I hope someone can help me out :)
For an O(N) solution, first reduce the array into an object that counts the number of occurrences of each name, and then filter the input by the occurrence count being 2:
const arr = [
{
Name: 'test',
coolProperty: 'yeahCool1'
},
{
Name: 'test1',
coolProperty: 'yeahCool2'
},
{
Name: 'test2',
coolProperty: 'yeahCool3'
},
{
Name: 'test3',
coolProperty: 'yeahCool4'
},
{
Name: 'test',
coolProperty: 'yeahCool5'
}
];
const counts = arr.reduce((a, { Name }) => {
a[Name] = (a[Name] || 0) + 1;
return a;
}, {});
console.log(arr.filter(({ Name }) => counts[Name] === 2));
You could use reduce() and filter() method to get the required result.
Using filter() method you need to check if length is greater than 2 then need it will be push in new array inside of reduce() method
DEMO
const arr =[{"Name":"test","coolProperty":"yeahCool1"},{"Name":"test1","coolProperty":"yeahCool2"},{"Name":"test2","coolProperty":"yeahCool3"},{"Name":"test3","coolProperty":"yeahCool4"},{"Name":"test","coolProperty":"yeahCool5"}];
let getCount = (name)=>{
return arr.filter(o => o.Name == name).length;
}
console.log(arr.reduce((r,item) => {
let len = getCount(item.Name);
return r.concat(len>1?item:[]);
}, []));
I see that you have already got an answer. So I thought of adding another way using map.
var counts = {};
var repeats = {};
arr.map(i => {
counts[i['Name']] = (counts[i['Name']] || []);
counts[i['Name']].push(i);
if (counts[i['Name']].length > 1) {
repeats[i['Name']] = counts[i['Name']];
}
});
console.log(repeats);
Not the best solution considering the performance. Just wanted to add an alternative method.
Hope it helps!!

Javascript: Filter array of objects

What am I doing wrong here?
var locations = [
{ id: 1, name: 'N'},
{ id: 2, name: 'P'}
]
var employee = { location_id: 1 }
locations.filter((location) => {
return location.id == employee.location_id
});
console.log(locations);
this returns undefined when I'm trying to make it return { id: 1, name: 'N'}.
filter() function is not mutable - which means it returns a new array with the filtered objects and do not 'mutate' the original array - you must assign it to another variable - see demo below:
locations = [
{ id: 1, name: 'N'},
{ id: 2, name: 'P'}
]
employee = { location_id: 1 }
var result = locations.filter((location) => {
return location.id == employee.location_id
})
console.log(result);
You need a variable for the result of filtering with Array#filter
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
var locations = [
{ id: 1, name: 'N'},
{ id: 2, name: 'P'}
],
employee = { location_id: 1 },
result = locations.filter((location) => {
return location.id == employee.location_id
});
console.log(result);
You need to store the result of .filter(). It doesn't mutate the original array.
On a side note, you can shorten your callback function by removing the curly brackets and return statement.
locations = locations.filter(loc => loc.id == employee.location_id);

Create new array from iterating JSON objects and getting only 1 of its inner array

See jsfiddle here: https://jsfiddle.net/remenyLx/2/
I have data that contains objects that each have an array of images. I want only the first image of each object.
var data1 = [
{
id: 1,
images: [
{ name: '1a' },
{ name: '1b' }
]
},
{
id: 2,
images: [
{ name: '2a' },
{ name: '2b' }
]
},
{
id: 3
},
{
id: 4,
images: []
}
];
var filtered = [];
var b = data1.forEach((element, index, array) => {
if(element.images && element.images.length)
filtered.push(element.images[0].name);
});
console.log(filtered);
The output needs to be flat:
['1a', '2a']
How can I make this prettier?
I'm not too familiar with JS map, reduce and filter and I think those would make my code more sensible; the forEach feels unnecessary.
First you can filter out elements without proper images property and then map it to new array:
const filtered = data1
.filter(e => e.images && e.images.length)
.map(e => e.images[0].name)
To do this in one loop you can use reduce function:
const filtered = data1.reduce((r, e) => {
if (e.images && e.images.length) {
r.push(e.images[0].name)
}
return r
}, [])
You can use reduce() to return this result.
var data1 = [{
id: 1,
images: [{
name: '1a'
}, {
name: '1b'
}]
}, {
id: 2,
images: [{
name: '2a'
}, {
name: '2b'
}]
}, {
id: 3
}, {
id: 4,
images: []
}];
var result = data1.reduce(function(r, e) {
if (e.hasOwnProperty('images') && e.images.length) r.push(e.images[0].name);
return r;
}, [])
console.log(result);
All answers are creating NEW arrays before projecting the final result : (filter and map creates a new array each) so basically it's creating twice.
Another approach is only to yield expected values :
Using iterator functions
function* foo(g)
{
for (let i = 0; i < g.length; i++)
{
if (g[i]['images'] && g[i]["images"].length)
yield g[i]['images'][0]["name"];
}
}
var iterator = foo(data1) ;
var result = iterator.next();
while (!result.done)
{
console.log(result.value)
result = iterator.next();
}
This will not create any additional array and only return the expected values !
However if you must return an array , rather than to do something with the actual values , then use other solutions suggested here.
https://jsfiddle.net/remenyLx/7/

Categories

Resources