How to match more than one property of an object - javascript

I can match a single property easy enough
var peoples = [
{ "name": "bob", "dinner": "pizza" },
{ "name": "john", "dinner": "sushi" },
{ "name": "larry", "dinner": "hummus" },
{ "name": "john", "dinner": "pie" }
];
$.each(peoples, function(i, val) {
$.each(val, function(key, name) {
if (name === "john")
console.log(key + " : " + name);
});
});
But since there are 2 johns how do I match a particular one (eg the john that like sushi) and then return the whole matched object (in json)? I tried adding another condition to the if statement but that didn't seem to work.
Thanks

you can use find to check exact match
var peoples = [
{ "name": "bob", "dinner": "pizza" },
{ "name": "john", "dinner": "sushi" },
{ "name": "larry", "dinner": "hummus" },
{ "name": "john", "dinner": "pie" }
];
var filteredResult = peoples.find(val => val.name ==="john" && val.dinner==="sushi");
console.log(filteredResult)

I don't know the context, but there could be two john and both with the dinner property set to pie. I would suggest using id for each entry in the array. If the array you are working with is the one you list, you could project/transform it using map before you perform searches. For example
const people = [
{ name: "bob", dinner: "pizza" },
{ name: "john", dinner: "sushi" },
{ name: "larry", dinner: "hummus" },
{ name: "john", dinner: "pie" },
];
const peopleList = people.map((person, id) => ({ id, ...person }));
console.log(peopleList);
// You could start from here to search by id

Consider the following.
var peoples = [{
"name": "bob",
"dinner": "pizza"
},
{
"name": "john",
"dinner": "sushi"
},
{
"name": "larry",
"dinner": "hummus"
},
{
"name": "john",
"dinner": "pie"
}
];
$.each(peoples, function(i, val) {
if (val.name == "john" && val.dinner == "sushi") {
console.log("Persons[" + i + "]." + Object.keys(val)[0] + ": " + val.name);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
This iterates all the items and compares elements of each.

_.filter by lodash
You can use filter method by lodash
Iterates over elements of collection, returning an array of all elements predicate returns truthy for.The predicate is invoked with three arguments: (value, index|key, collection).It return a new array
https://lodash.com/docs/4.17.15#filter
Example for filter usage on lodash
var users = [{
'user': 'barney',
'age': 36,
'active': true
},
{
'user': 'fred',
'age': 40,
'active': false
},
{
'user': 'fred',
'age': 39,
'active': true
}
];
console.log("matches:", _.filter(users, function(o) {
return !o.active;
}));
// => [{ active: true, age: 36, user: "barney"}]
// The `_.matches` iteratee shorthand.
console.log("_.matches` iteratee", _.filter(users, {
'user': 'fred',
'active': true
}));
// => [{ active: true, age: 39, user: "fred"}]
// The `_.matchesProperty` iteratee shorthand.
console.log("matchs poperty", _.filter(users, ['active', false]));
// => objects for ['fred']
// The `_.property` iteratee shorthand.
_.filter(users, 'active');
// => objects for ['barney']
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
_.where by underscore.js
You can also use where method of underscore.js
Looks through each value in the list, returning an array of all the values that
matches the key-value pairs listed in properties.
_.where(list, properties)
Example of _.where usage
_.where(listOfPlays, {author: "Shakespeare", year: 1611});
You can basicaly use filter method in plain vanilla javascript
var peoples = [
{ "name": "bob", "dinner": "pizza" },
{ "name": "john", "dinner": "sushi" },
{ "name": "john", "dinner": "sushi" },
{ "name": "larry", "dinner": "hummus" },
{ "name": "john", "dinner": "pie" }
];
var dinner = peoples.filter(e=>e.name ==="john" && e.dinner==="sushi");
console.log(dinner)
You may also use jquery grep
var peoples = [
{ "name": "bob", "dinner": "pizza" },
{ "name": "john", "dinner": "sushi" },
{ "name": "john", "dinner": "sushi" },
{ "name": "larry", "dinner": "hummus" },
{ "name": "john", "dinner": "pie" }
];
var dinner = $.grep(peoples, function(people) {
return people.name === "john" && people.dinner === "sushi";
});
console.log(dinner)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Find vs filter
var peoples = [
{ "name": "bob", "dinner": "pizza" },
{ "name": "john", "dinner": "sushi" },
{ "name": "john", "dinner": "sushi" },
{ "name": "larry", "dinner": "hummus" },
{ "name": "john", "dinner": "pie" }
];
var filterDinner = peoples.filter(e=>e.name ==="john" && e.dinner==="sushi");
// return all matching results
console.log('filter dinner -:', filterDinner);
var findDinner = peoples.find(e=>e.name ==="john" && e.dinner==="sushi");
//returns the first matching rslt
console.log('find dinner -:', findDinner);
Find was not recommended because it return the first matching result and suppose we have more matching results they are missed out.

You could set up a function to define your search terms then use Array.filter:
const peoples = [
{ "name": "bob", "dinner": "pizza" },
{ "name": "john", "dinner": "sushi" },
{ "name": "larry", "dinner": "hummus" },
{ "name": "john", "dinner": "pie" }
];
searchTerms = (person) => {
return person.name === "john" && person.dinner === "sushi";
}
console.log(peoples.filter(searchTerms));
// [{ "name": "john", "dinner": "sushi" }]

Related

How do I map array of objects to an existing array on MongoDB

Please how can I make this work on mongoDB.
For each item in an array, fetch data which contains the item from another collection.
For example:
"users" : [{
"name": "John doe",
"age": 51
},
{
"name": "Jake kim",
"age": 50
},
{
"name": "Jim son",
"age": 51
}]
On another collection I have
"age": [50,51,52,53,54]
Now my desire result is
"50" : [{
"name": "Jake kim",
"age": 50
}],
"51" : [{
"name": "John doe",
"age": 51
},
{
"name": "Jim son",
"age": 51
}]
You can do this. Get the array of users.
const users = [{ "name": "John doe", "age": 51 }, { "name": "Jake kim", "age": 50 }, { "name": "Jim son", "age": 51 }]
Get the array of ages
const age = [50,51,52,53,54]
Then you can map through the array of ages, returning an object that has the user that has the same age, here is the algorithm.
const mapped = age.map(age => {
const user = {}
user[age] = users.find(ob => ob.age === age);
return user;
})
If you print out the mapped result. This is what it will look like, For the ages that we couldn't find their users, they just have an undefined value.
console.log(mapped)
[
{ '50': { name: 'Jake kim', age: 50 } },
{ '51': { name: 'John doe', age: 51 } },
{ '52': undefined },
{ '53': undefined },
{ '54': undefined }
]
I don't think you'll need the age data in your case. However I've provided the both versions which one use the age list but other does not. Please find them below.
const users = [{ "name": "John doe", "age": 51 }, { "name": "Jake kim", "age": 50 }, { "name": "Jim son", "age": 51 }];
const age = [50, 51, 52, 53, 54];
const desired = users.reduce((prev, cur) => {
(prev[cur.age] ?? (prev[cur.age] = [])).push(cur);
return prev;
}, {});
console.log("This is the expected result", desired);
const desired2 = users.reduce((prev, cur) => {
(prev[cur.age] ?? (prev[cur.age] = [])).push(cur);
return prev;
}, age.reduce((prev, cur) => {
prev[cur] = [];
return prev;
}, {}));
console.log("This is the expected result with empty ages", desired2);

How to remove a child object from a JSON object using javascript

I'm trying to search through a JSON object to find the pet-rock that I want to delete. Here is a simple JSON that I'm working on:
myData.json:
{
"data": [
{
"name": "John",
"age": "25",
"pet-rocks": [
{
"name": "Travis",
"age": "9"
},
{
"name": "Steven",
"age": "5"
},
{
"name": "Oliver",
"age": "7"
}
]
},
{
"name": "Jane",
"age": "25",
"pet-rocks": [
{
"name": "Jesse",
"age": "4"
},
{
"name": "Carol",
"age": "8"
},
{
"name": "Jake",
"age": "7"
}
]
}
]
}
I would like to do a search for "Steven" and remove that pet-rock from the list. Here are the things I've tried:
MyJSFile.js:
const myDataObject = require('./myData.json');
for (let key in myDataObject) {
let value = myDataObject[key];
if (value === "Steven")
{
delete myDataObject[key];
}
//To see if I get the data I want
console.log(key, value);
}
However, my output is strange and I'm not sure how to get to that child node of petrock. It appears that the petrocks are in object form, and I'm not sure how to get to them. here is the ouput of my console below. I assume it didn't get delete as there are still 3 petrock objects in the data.
data [
{
name: 'Robert',
age: '25',
'pet-rocks': [ [Object], [Object], [Object] ]
},
{
name: 'Robert',
age: '25',
'pet-rocks': [ [Object], [Object], [Object] ]
}
]
Any help or suggestions would be greatly appreciated! Thanks!
The pet rock named Steven is not a direct child of myDataObject, so you can't delete it like that. You can loop through the "data" array, rebuilding the "pet-rocks" array for each element. A simple filter to remove any pet rocks named Steven should work.
const myDataObject = {
"data": [
{
"name": "John",
"age": "25",
"pet-rocks": [
{
"name": "Travis",
"age": "9"
},
{
"name": "Steven",
"age": "5"
},
{
"name": "Oliver",
"age": "7"
}
]
},
{
"name": "Jane",
"age": "25",
"pet-rocks": [
{
"name": "Jesse",
"age": "4"
},
{
"name": "Carol",
"age": "8"
},
{
"name": "Jake",
"age": "7"
}
]
}
]
};
myDataObject.data.forEach(d => {
d["pet-rocks"] = d["pet-rocks"].filter(rock => rock.name !== "Steven");
});
console.log(myDataObject);

How to merge children in multiple JSON objects?

I have the following JavaScript object
[
{
"familyName": "Smith",
"children": [
{ "firstName": "John" },
{ "firstName": "Mike" }
]
},
{
"familyName": "Williams",
"children": [
{ "firstName": "Mark" },
{ "firstName": "Dave" }
]
},
{
"familyName": "Jones",
"children": [
{ "firstName": "Mary" },
{ "firstName": "Sue" }
]
}
]
I’d like to create an array of all children i.e.
[
{ "FirstName": "John" },
{ "FirstName": "Mike" },
{ "FirstName": "Mark" },
{ "FirstName": "Dave" },
{ "FirstName": "Mary" },
{ "FirstName": "Sue" }
]
I am using jQuery.
I have looked at posts that describe merging or concatenating arrays but not those of child arrays: e.g. Merge/flatten an array of arrays in JavaScript?
I believe I could loop through the families and add the children arrays but suspect that there is a 'one-liner' for this?
I tested in the console:
//The families(duh)
const families = [
{
"familyName": "Smith",
"children": [
{ "firstName": "John" },
{ "firstName": "Mike" }
]
},
{
"familyName": "Williams",
"children": [
{ "firstName": "Mark" },
{ "firstName": "Dave" }
]
},
{
"familyName": "Jones",
"children": [
{ "firstName": "Mary" },
{ "firstName": "Sue" }
]
}
]
//Just flatten the children:
var children = [].concat.apply([], families.map(family => family.children));
//Outputs
console.log(children);
A solution without jQuery would be to use reduce to extract children from their families (sounds a bit rough, sorry for that).
families.reduce(function(list, family){
return list.concat(family.children);
}, []);
You can do this by using $.map:
var a = [
{
"familyName": "Smith",
"children": [
{ "firstName": "John" },
{ "firstName": "Mike" }
]
},
{
"familyName": "Williams",
"children": [
{ "firstName": "Mark" },
{ "firstName": "Dave" }
]
},
{
"familyName": "Jones",
"children": [
{ "firstName": "Mary" },
{ "firstName": "Sue" }
]
}
]
console.log($.map(a, function(it){
return it.children;
}));
// Or ES6
$.map(a, it => it.children);
Result:
[
{
"firstName":"John"
},
{
"firstName":"Mike"
},
{
"firstName":"Mark"
},
{
"firstName":"Dave"
},
{
"firstName":"Mary"
},
{
"firstName":"Sue"
}
]
Try with Array#forEach method .then push the children object with new array
var families = [ { "familyName": "Smith", "children": [ { "firstName": "John" }, { "firstName": "Mike" } ] }, { "familyName": "Williams", "children": [ { "firstName": "Mark" }, { "firstName": "Dave" } ] }, { "familyName": "Jones", "children": [ { "firstName": "Mary" }, { "firstName": "Sue" } ] } ]
var children = [];
families.forEach(family => family.children.forEach(child => children.push(child)));
console.log(children);

Rebuild nested array

I have an nested array that i want to rebuild based on age value:
//Data
data = {"people":
[{"male_1": [
{"name": "Bob" ,"age": "32"},
{"name":"Mike", "age":"31"}
]},
{"female_2": [
{"name":"Jessica", "age": "24"},
{"name":"Ann", "age": "23"}
]}
[{"male_3": [
{"name": "Tom" ,"age": "31"},
{"name":"John", "age":"29"}
]}, ...
]}
New array should looks like:
people = [{"male_1": [
{"name": "Bob" ,"age": "32"}
]},
[{"male_3": [
{"name": "Tom" ,"age": "31"}
]},
{"female_2": [
{"name":"Jessica", "age": "24"}
]}, ...
]}
Based on this example i need to find the largest age of all "persons" then add this person to array then do same with the next one. The age can be same in this case there is no difference who goes first.
With the next function i can find first one and push it to new array, but how find next one?
var age = 0;
data["people"].forEach(function(item) {
for (var key in item) {
if (item.hasOwnProperty(key)) {
item[key].forEach(function(person) {
if (person.age > age) {
age = person.age;
oldest_person = person
}
});
}
}
});
console.log(oldest_person);
here is another interpretation. This one uses the native Array.prototype.sort as the helper function.
var data = { "people": [{ "male_1": [{ "name": "Bob", "age": "32" }, { "name": "Mike", "age": "31" }] }, { "female_2": [{ "name": "Jessica", "age": "24" }, { "name": "Ann", "age": "23" }] }, { "male_3": [{ "name": "Tom", "age": "31" }, { "name": "John", "age": "29" }] }] },
oldies = [],
peopleByAge = data.people.map(function(group){
for( var name in group ){
group[name] = group[name].sort(sortBy('age'));
oldies.push( group[name][0] );
}
return group;
});
// sort by an object key
function sortBy( key ){
return function(a, b){
return parseInt(a[ key ]) < parseInt(b[ key ]);
}
}
document.write('<pre>' + JSON.stringify({ oldies: oldies.sort(sortBy('age')), peopleByAge: peopleByAge }, 0, 2) + '</pre>');
Try this:
var age = 0;
var oldest_person = [];
var data = {"people":
[
{"male_1": [
{"name": "Bob" ,"age": "32"},
{"name":"Mike", "age":"31"}
]},
{"female_2": [
{"name":"Jessica", "age": "24"},
{"name":"Ann", "age": "23"}
]},
{"male_3": [
{"name": "Tom" ,"age": "31"},
{"name":"John", "age":"29"}
]}
]};
data["people"].forEach(function(item) {
for (var key in item) {
if (item.hasOwnProperty(key)) {
var age = 0;
var name = key;
var oldest = null;
item[key].forEach(function(person) {
// Determine the oldest person in each group ("male_1", "female_2", "male_3", ...)
if (person.age > age) {
age = person.age;
oldest = person;
}
});
// Push the oldest person into the 'oldest_person' array
var group = {};
group[name] = [ oldest ];
oldest_person.push(group);
}
}
});
console.log(oldest_person);
You can use some Array methods, like Array.prototype.forEach(), Array.prototype.reduce() and Object.keys().
var data = { "people": [{ "male_1": [{ "name": "Bob", "age": "32" }, { "name": "Mike", "age": "31" }] }, { "female_2": [{ "name": "Jessica", "age": "24" }, { "name": "Ann", "age": "23" }] }, { "male_3": [{ "name": "Tom", "age": "31" }, { "name": "John", "age": "29" }] }] },
people = [];
data.people.forEach(function (a) {
Object.keys(a).forEach(function (k) {
var o = {};
o[k] = a[k].reduce(function (c, d) {
return c.age > d.age ? c : d;
});
people.push(o);
});
});
document.write('<pre>' + JSON.stringify(people, 0, 4) + '</pre>');

linq.js Group By then Group By, How can it be achieved?

I want something that would result in this
[{
firstName: "Sam",
lastName: "Smith"
}, {
firstName: "Sam",
lastName: "Doe"
}, {
firstName: "Sam",
lastName: "Doe"
}, {
firstName: "Sam",
lastName: "Joe"
}]
Being something like this, with the exception of the number of columns to group with which is not fixed and the order of the columns as well
[{
"Sam": [{
"Smith": [{
firstName: "Sam",
lastName: "Smith"
}]
}, {
"Doe": [{
firstName: "Sam",
lastName: "Doe"
}, {
firstName: "Sam",
lastName: "Doe"
}]
}, {
"Joe": [{
firstName: "Sam",
lastName: "Joe"
}]
}]
}]
I want to be able to build something like the following photo demonstrates
I tried several times but i can't get a grasp on it, please help me :).
I propose a different output structure. Your structure seems convenient at first glance, but in further processing it will prove unnecessarily difficult to handle.
I would suggest this generic structure:
[
{
key: "group 1",
items: [{
key: "group 1.1",
items: [ {}, {}, {} ]
}, {
key: "group 1.2",
items: [ {}, {} ]
}]
}, {
key: "group 2",
items: [{
key: "group 2.1",
items: [ {}, {}, [}, {} ]
}, {
key: "group 2.2",
items: [ {} ]
}]
}
]
You can create a structure like this relatively easily:
var grouped = Enumerable.From(input).GroupBy("$.firstName", "", function(key, e) {
return {
key: key,
items: e.GroupBy("$.lastName", "", function (key, e) {
return {
key: key,
items: e.ToArray()
};
}).ToArray()
};
}).ToArray();
when applied to this input:
var input = [{
firstName: "Sam",
lastName: "Smith"
}, {
firstName: "Sam",
lastName: "Doe"
}, {
firstName: "Sam",
lastName: "Doe"
}, {
firstName: "Sam",
lastName: "Joe"
},{
firstName: "John",
lastName: "Joe"
}];
results in
[
{
"key": "Sam",
"items": [
{
"key": "Smith",
"items": [
{
"firstName": "Sam",
"lastName": "Smith"
}
]
},
{
"key": "Doe",
"items": [
{
"firstName": "Sam",
"lastName": "Doe"
},
{
"firstName": "Sam",
"lastName": "Doe"
}
]
},
{
"key": "Joe",
"items": [
{
"firstName": "Sam",
"lastName": "Joe"
}
]
}
]
},
{
"key": "John",
"items": [
{
"key": "Joe",
"items": [
{
"firstName": "John",
"lastName": "Joe"
}
]
}
]
}
]
Edit: To allow dynamically configurable grouping and ordering, a more advanced approach must be taken:
// Enumerable, definition => Enumerable
function applyOrder(items, definition) {
var i, prop, prefix, suffix, orderFunc;
if (!items) return;
if (!definition) return items;
for (i = 0; i < definition.length; i++) {
// definition[i] is either "propertyName" or "propertyName DESC"
prop = (definition[i] + " ").split(" ");
prefix = i === 0 ? "OrderBy" : "ThenBy";
suffix = prop[1].toUpperCase() === "DESC" ? "Descending" : "";
orderFunc = prefix + suffix;
items = items[orderFunc]("$." + prop[0]);
}
return items;
}
// Enumerable, definition => Enumerable
function applyGroup(items, definition) {
if (!items) return;
if (!definition) return items;
items = applyOrder(items, definition.order);
if (!definition.group) return items;
return items.GroupBy("$." + definition.group, "", function (key, e) {
return {
group: definition.group,
key: key,
items: applyGroup(e, definition.then).ToArray()
};
});
}
// Array, definition => Array
function applyStructure(items, definition) {
if (!items) return;
if (!definition) return items;
return applyGroup(Enumerable.From(items), definition).ToArray();
}
used like this:
var result = applyStructure(companies, {
group: "country",
order: ["country"],
then: {
group: "city",
order: ["city"],
then: {
order: ["companyName DESC"]
}
}
});
live at: http://jsfiddle.net/Tomalak/xth6ayuo/

Categories

Resources