Related
Here i have skills array and employees array and i am trying to get the employees that includes all the skills that are included in skills array using reduce, filter or find method. I am trying to stored the filtered employees in filteredItems but got stuck in it.
filteredItems = Skills?.length>0 ?
Employees?.filter((item) => {
return item.Skills.find((ele) => {
return Skills.find((el) => {
if(el.value === ele.id){
return ele
}
})
})
}) : []
Below are the arrays mentioned.
Skills Array
[
{
"value": 6,
"label": "Marketing"
},
{
"value": 20,
"label": "Golang"
}
]
Employees Array
[
{
"name": "Hassan",
"id": 56,
"Skills": [
{
"id": 20,
"name": "Golang",
},
],
},
{
"name": "Haroon",
"id": 95,
"Skills": [
{
"id": 6,
"name": "Marketing",
},
{
"id": 20,
"name": "Golang",
},
],
},
]
For example, in above scenario of arrays it should return employee of id of 95 not return employee of id 56 because it includes skills but not all that are mention in skills array.
I found it easier to first encapsulate an array of skill IDs to search for.
let skillIds = Skills.map(s => s.value);
Then I filtered and compared the end result to the length of the skill Ids array:
let filteredItems = Skills?.length > 0 ?
Employees?.filter(item => item.Skills.filter( s =>
skillIds.includes(s.id)).length==skillIds.length): []
let Skills = [{
"value": 6,
"label": "Marketing"
}, {
"value": 20,
"label": "Golang"
}]
let Employees = [{
"name": "Hassan",
"id": 56,
"Skills": [{
"id": 20,
"name": "Golang",
}],
}, {
"name": "Haroon",
"id": 95,
"Skills": [{
"id": 6,
"name": "Marketing",
},
{
"id": 20,
"name": "Golang",
},
],
}, ]
let skillIds = Skills.map(s => s.value);
let filteredItems = Skills?.length > 0 ?
Employees?.filter(item => item.Skills.filter( s => skillIds.includes(s.id)).length==skillIds.length): []
console.log(filteredItems)
You could create another property in the employees array.. call it "QUalified". Default it to true, then set it to false when the employee doesn't have a skill in the skills array.
let arSkills = [
{
"value": 6,
"label": "Marketing"
},
{
"value": 20,
"label": "Golang"
}
];
let arEmp = [
{
"name": "Hassan",
"id": 56,
"Skills": [
{
"id": 20,
"name": "Golang",
},
],
},
{
"name": "Haroon",
"id": 95,
"Skills": [
{
"id": 6,
"name": "Marketing",
},
{
"id": 20,
"name": "Golang",
},
],
},
];
arEmp.forEach(ele =>{
ele.Qualified = true;
let arTmp = [];
for(let {id} of ele.Skills)
arTmp.push(id)
for(let {value} of arSkills)
if(!arTmp.includes(value))
ele.Qualified = false
});
let arQual = arEmp.filter((ele) =>{
return ele.Qualified
});
console.log(arQual);
I want to return only matches results.
My array:
products: [
{
"id": 1,
"name": "Product 1",
"concepts": [
{
"id": 10,
"name": "Blabla"
},
{
"id": 15,
"name": "Zlazla"
}
]
},
{
"id": 2,
"name": "Product 2",
"concepts": [
{
"id": 14,
"name": "Gulagula"
},
{
"id": 15,
"name": "Zlazla"
}
]
}
]
I want to filter products which only have one of the concepts below.
concepts array:
['14', '15']
Couldn't solve this in an easy way.
You can try this way:
var products= [
{
"id": 1,
"name": "Product 1",
"concepts": [
{
"id": 10,
"name": "Blabla"
},
{
"id": 15,
"name": "Zlazla"
}
]
},
{
"id": 2,
"name": "Product 2",
"concepts": [
{
"id": 14,
"name": "Gulagula"
},
{
"id": 15,
"name": "Zlazla"
}
]
}
]
var products = products.filter((product) => product.concepts = product.concepts.filter( (x) => x.id == 14 || x.id == 15));
console.log(products);
how to get the respective nested JSON object based on Id. For example below is my complete JSON.
[
{
"id": 1,
"title": "ASD Headquarters",
"items": [
{
"id": 11,
"title": "San Jose",
"items": [
{
"id": 13,
"title": "Jensen Chapman's Team",
"items": [
{
"id": 14,
"title": "Jimmy John"
},
{
"id": 15,
"title": "Daniel Mills"
},
{
"id": 16,
"title": "Chris Boden"
}
]
}
]
},
{
"id": 12,
"title": "Irvine",
"items": [
{
"id": 23,
"title": "Tracey Chapman's Team",
"items": [
{
"id": 24,
"title": "San Jesus"
},
{
"id": 25,
"title": "Fat Albert"
},
{
"id": 26,
"title": "Connor McDavid"
}
]
}
]
},
{
"id": 30,
"title": "San Diego",
"items": [
{
"id": 31,
"title": "Duran Duran's Team",
"items": [
{
"id": 32,
"title": "Amberlynn Pinkerton"
},
{
"id": 33,
"title": "Tony Mejia"
},
{
"id": 34,
"title": "Richard Partridge"
},
{
"id": 35,
"title": "Elliot Stabler"
}
]
},
{
"id": 40,
"title": "Steely Dan's Team",
"items": [
{
"id": 36,
"title": "Tony Stark"
},
{
"id": 37,
"title": "Totally Rad"
},
{
"id": 38,
"title": "Matt Murdock"
},
{
"id": 39,
"title": "Stan Lee"
}
]
}
]
}
]
}
]
From the above json how do i filter only particular nested object which have id as 11 => {"id": 11} using underscore.js
Output which i required is : {
"id":11,
"title":"San Jose",
"items":[
{
"id":13,
"title":"Jensen Chapman's Team",
"items":[
{
"id":14,
"title":"Jimmy John"
},
{
"id":15,
"title":"Daniel Mills"
},
{
"id":16,
"title":"Chris Boden"
}
]
}
]
}
You can use a recursive algorithm to look for an object in the current array as well as the nested ones.
var data = [{"id":1,"title":"ASD Headquarters","items":[{"id":11,"title":"San Jose","items":[{"id":13,"title":"Jensen Chapman's Team","items":[{"id":14,"title":"Jimmy John"},{"id":15,"title":"Daniel Mills"},{"id":16,"title":"Chris Boden"}]}]},{"id":12,"title":"Irvine","items":[{"id":23,"title":"Tracey Chapman's Team","items":[{"id":24,"title":"San Jesus"},{"id":25,"title":"Fat Albert"},{"id":26,"title":"Connor McDavid"}]}]},{"id":30,"title":"San Diego","items":[{"id":31,"title":"Duran Duran's Team","items":[{"id":32,"title":"Amberlynn Pinkerton"},{"id":33,"title":"Tony Mejia"},{"id":34,"title":"Richard Partridge"},{"id":35,"title":"Elliot Stabler"}]},{"id":40,"title":"Steely Dan's Team","items":[{"id":36,"title":"Tony Stark"},{"id":37,"title":"Totally Rad"},{"id":38,"title":"Matt Murdock"},{"id":39,"title":"Stan Lee"}]}]}]}];
console.log(find(12, data));
function find(id, [head, ...tail]) {
if (!head)
return null;
return checkObj(id, head) || find(id, tail);
}
function checkObj(id, obj) {
return obj.id === id ? obj : find(id, obj.items || [])
}
This also uses parameter destructuring in order to conveniently separate the "head" of the array from its "tail".
It could also be done within a single function.
var data = [{"id":1,"title":"ASD Headquarters","items":[{"id":11,"title":"San Jose","items":[{"id":13,"title":"Jensen Chapman's Team","items":[{"id":14,"title":"Jimmy John"},{"id":15,"title":"Daniel Mills"},{"id":16,"title":"Chris Boden"}]}]},{"id":12,"title":"Irvine","items":[{"id":23,"title":"Tracey Chapman's Team","items":[{"id":24,"title":"San Jesus"},{"id":25,"title":"Fat Albert"},{"id":26,"title":"Connor McDavid"}]}]},{"id":30,"title":"San Diego","items":[{"id":31,"title":"Duran Duran's Team","items":[{"id":32,"title":"Amberlynn Pinkerton"},{"id":33,"title":"Tony Mejia"},{"id":34,"title":"Richard Partridge"},{"id":35,"title":"Elliot Stabler"}]},{"id":40,"title":"Steely Dan's Team","items":[{"id":36,"title":"Tony Stark"},{"id":37,"title":"Totally Rad"},{"id":38,"title":"Matt Murdock"},{"id":39,"title":"Stan Lee"}]}]}]}];
console.log(find(12, data));
function find(id, [head, ...tail]) {
if (!head)
return null;
if (head.id === id)
return head;
return find(id, head.items || []) || find(id, tail);
}
I have 2 arrays of objects: itemsList and itemsFetched. All of the objects inside each array have the same structure (nr of key/values). One of those keys has the same 'meaning' but a different name (item_id on itemsList, id on itemsFetched ). Their values are the same.
I need to filter the itemsList array and leave only the objects that have the item_id value equal to the id value on itemsFetched. Then copy(add) the key/value count from each object on the itemsFetched array (which matches the item_id=id) to the filtered array.
I've a working code but I'm sure it isnt the best way to solve this problem. I've already asked something similar before (regarding the 'filter' part) which solved my problem, but since I had to add the 'count' part after the filtering, I ended up refactoring the whole thing.
itemsList (sample)
[
{
"id": 0,
"name": "Egg",
"img": "http://www.serebii.net/pokemongo/items/egg.png"
},
{
"id": 1,
"name": "Pokeball",
"img": "http://www.serebii.net/pokemongo/items/20pokeballs.png"
},
{
"id": 2,
"name": "Greatball",
"img": "http://www.serebii.net/pokemongo/items/greatball.png"
},
{
"id": 401,
"name": "Incense",
"img": "http://www.serebii.net/pokemongo/items/incense.png"
},
{
"id": 901,
"name": "Incubator (Unlimited)",
"img": "http://www.serebii.net/pokemongo/items/eggincubator.png"
}
]
itemsFetched (sample)
[
{
"item_id": 1,
"count": 50,
"unseen": true
},
{
"item_id": 401,
"count": 2,
"unseen": true
},
{
"item_id": 901,
"count": 1,
"unseen": true
}
]
resultArray (what I want in the end)
[
{
"id": 1,
"name": "Pokeball",
"count": 50,
"img": "http://www.serebii.net/pokemongo/items/20pokeballs.png",
},
{
"id": 401,
"name": "Incense",
"count": 2,
"img": "http://www.serebii.net/pokemongo/items/incense.png"
},
{
"id": 901,
"name": "Incubator (Unlimited)",
"count": 1,
"img": "http://www.serebii.net/pokemongo/items/eggincubator.png"
}
]
my current code (working)
let arr = [];
itemsFetched.forEach((item) => {
itemsList.forEach((item2) => {
if (item.item_id === item2.id) {
arr.push({
"id": item.item_id,
"name": item2.name,
"count": item.count,
"img": item2.img
});
}
});
});
PS: I'm able to use ES6/7 syntax/features.
You can use hash map to reduce Time complexitly, your algorithm is O(m*n), The follow is O(m+n+r)
const itemsMap = itemsList.reduce((map, item) => {
map[item.id] = item
return map
}, {})
const results = itemsFetched
.filter((item) => itemsMap.hasOwnProperty(item.item_id))
.map((item) => ({
id: item.item_id,
name: itemsMap[item.item_id].name,
count: item.count,
img: itemsMap[item.item_id].img,
}))
Use a for ... of loop (an ES6 feature) in conjunction with Array#map.
This makes it much easier to return the merged object the first time you find a match, which is a logically optimization because neither list should contain more than one entry with a given id.
const result = itemsFetched.map(data => {
for (let item of itemsList) {
if (data.item_id === item.id) {
return {
id: item.id,
name: item.name,
count: data.count,
img: item.img
}
}
}
})
Snippet:
const itemsList = [{
"id": 0,
"name": "Egg",
"img": "http://www.serebii.net/pokemongo/items/egg.png"
}, {
"id": 1,
"name": "Pokeball",
"img": "http://www.serebii.net/pokemongo/items/20pokeballs.png"
}, {
"id": 2,
"name": "Greatball",
"img": "http://www.serebii.net/pokemongo/items/greatball.png"
}, {
"id": 401,
"name": "Incense",
"img": "http://www.serebii.net/pokemongo/items/incense.png"
}, {
"id": 901,
"name": "Incubator (Unlimited)",
"img": "http://www.serebii.net/pokemongo/items/eggincubator.png"
}]
const itemsFetched = [{
"item_id": 1,
"count": 50,
"unseen": true
}, {
"item_id": 401,
"count": 2,
"unseen": true
}, {
"item_id": 901,
"count": 1,
"unseen": true
}]
const result = itemsFetched.map(data => {
for (let item of itemsList) {
if (data.item_id === item.id) {
return {
id: item.id,
name: item.name,
count: data.count,
img: item.img
}
}
}
})
console.log(result)
One way to improve is to use for..of statement instead of forEach for the inner loop. This helps break from the loop once the id matches. There is no direct way to break from forEach method.
let arr = [];
itemsFetched.forEach((item) => {
for (let item2 of itemsList) {
if (itemsFetched.item_id === itemsList.id) {
arr.push({
"id": itemsFetched.item_id,
"name": itemsList.name,
"count": itemsFetched.count,
"img": itemsList.img
});
break;
}
}
});
Like this?
var itemsList = [
{
"id": 0,
"name": "Egg",
"img": "http://www.serebii.net/pokemongo/items/egg.png"
},
{
"id": 1,
"name": "Pokeball",
"img": "http://www.serebii.net/pokemongo/items/20pokeballs.png"
},
{
"id": 2,
"name": "Greatball",
"img": "http://www.serebii.net/pokemongo/items/greatball.png"
},
{
"id": 401,
"name": "Incense",
"img": "http://www.serebii.net/pokemongo/items/incense.png"
},
{
"id": 901,
"name": "Incubator (Unlimited)",
"img": "http://www.serebii.net/pokemongo/items/eggincubator.png"
}
];
var itemsFetched = [
{
"item_id": 1,
"count": 50,
"unseen": true
},
{
"item_id": 401,
"count": 2,
"unseen": true
},
{
"item_id": 901,
"count": 1,
"unseen": true
}
]
let arr = [];
itemsFetched.forEach((item) => {
itemsList.forEach((item2) => {
if (item.item_id == item2.id) {
arr.push({
"id": item.item_id,
"name": item2.name,
"count": item.count,
"img": item2.img
});
}
});
});
console.log(arr);
I have a JSON dataset which could be very large when it returns, with the following structure for each object:
{
"ctr": 57,
"averageECPC": 23,
"cost": 2732.54,
"margin": 66,
"profit": 2495.9,
"property": {
"value": "Izzby",
"uri": "/Terrago/2"
},
"status": {
"content": "<p>Some Content</p>",
"stage": 1
},
"alerts": {
"status": 2
},
"revenue": {
"value": 2573.13,
"compare": 0
},
"children": [{
"ctr": 79,
"averageECPC": 54,
"cost": 3554.78,
"margin": 88,
"profit": 3145.81,
"property": {
"value": "Comvex",
"uri": "/Octocore/4"
},
"status": {
"content": "<p>Some Content</p>",
"stage": 1
},
"alerts": {
"status": 2
},
"revenue": {
"value": 1247.92,
"compare": 0
}
}]
}
Now I want to search all objects in the array and return only objects which include a string of some sort, but I only want to search certain properties.
I basically have another array which contains the keys I want to search, e.g.
const iteratees = ['ctr', 'property.value', 'status.stage']
I have lodash available within the project, but I have no idea where to start.
Any ideas?
You could use filter(), some() and reduce() to do this.
const iteratees = ['ctr', 'property.value', 'status.stage'];
var searchFor = 'lo';
var result = arr.filter(function(o) {
return iteratees.some(function(e) {
var res = e.split('.').reduce(function(a, b) {
if(a) return a[b];
}, o);
if(res) {
if((res).toString().indexOf(searchFor) != -1) return true;
}
})
})
var arr = [{
"ctr": 'lorem',
"averageECPC": 23,
"cost": 2732.54,
"margin": 66,
"profit": 2495.9,
"property": {
"value": "Izzby",
"uri": "/Terrago/2"
},
"status": {
"content": "<p>Some Content</p>",
"stage": 1
},
"alerts": {
"status": 2
},
"revenue": {
"value": 2573.13,
"compare": 0
},
"children": [{
"ctr": 79,
"averageECPC": 54,
"cost": 3554.78,
"margin": 88,
"profit": 3145.81,
"property": {
"value": "Comvex",
"uri": "/Octocore/4"
},
"status": {
"content": "<p>Some Content</p>",
"stage": 1
},
"alerts": {
"status": 2
},
"revenue": {
"value": 1247.92,
"compare": 0
}
}]
}, {
name: 'lorem',
ctr: 12,
property: {
value: 1
},
status: {
stage: 1
}
}, {
name: 'ipsum'
}]
const iteratees = ['ctr', 'property.value', 'status.stage'];
var searchFor = 'lo';
var result = arr.filter(function(o) {
return iteratees.some(function(e) {
var res = e.split('.').reduce(function(a, b) {
if (a) return a[b];
}, o);
if (res) {
if ((res).toString().indexOf(searchFor) != -1) return true;
}
})
})
console.log(result)