I need help putting together an array search that is based on multiple conditions. Furthermore, all the conditions are conditional, meaning I may or may not need to filter on those conditions. What I have:
Array of objects to filter:
var data = [{
"_id" : ObjectId("583f6e6d14c8042dd7c979e6"),
"transid" : 1,
"acct" : "acct1",
"transdate" : ISODate("2012-01-31T05:00:00.000Z"),
"category" : "category1",
"amount" : 103
},
{
"_id" : ObjectId("583f6e6d14c8042dd7c2132t6"),
"transid" : 2,
"acct" : "acct2",
"transdate" : ISODate("2012-01-31T05:00:00.000Z"),
"category" : "category2",
"amount" : 103
},
{
"_id" : ObjectId("583f6e6d14c8042dd7c2132t6"),
"transid" : 3,
"acct" : "acct2",
"transdate" : ISODate("2016-07-31T05:00:00.000Z"),
"category" : "category1",
"amount" : 103
},
{
"_id" : ObjectId("583f6e6d14c8042dd7c2132t6"),
"transid" : 4,
"acct" : "acct2",
"transdate" : ISODate("2012-01-31T05:00:00.000Z"),
"category" : "category2",
"amount" : 103
},
{
"_id" : ObjectId("583f6e6d14c8042dd7c2132t6"),
"transid" : 5,
"acct" : "acct2",
"transdate" : ISODate("2012-01-31T05:00:00.000Z"),
"category" : "category3",
"amount" : 103
},
{
"_id" : ObjectId("583f6e6d14c8042dd7c152g2"),
"transid" : 6,
"acct" : "acct3",
"transdate" : ISODate("2016-10-31T05:00:00.000Z"),
"category" : "category3",
"amount" : 103
}]
I am filtering the above array of objects based on another array of mixed elements. The elements represent the following search fields:
"searchstring": to search on all fields in the data array for any
matched text sequence
object with key values reprsenting account type and a true or false
for value indicating if it should be used to filter
startdate to filter transdate on
enddate to filter transdate
category name to filter category on
The array that has the search conditions looks like this (but if some of the fields are not necessary they will be set to undefined or just an empty string or array):
var filtercondition = {
"p",
{acct1:true,acct2:false,acct3:true...}
"2016-06-01",
"2016-11-30",
"category3"
}
What is the best way to accomplish this? What I've devised is a separate search for each element in the filter array, but this seems non optimal and very tedious. I'm open to a redesign of my setup...
// You wrote that it's an array, so changed the braces
var filtercondition = ["p",
{acct1:true,acct2:false,acct3:true...}
"2016-06-01",
"2016-11-30",
"category3"
];
var filtered = data.filter(o => {
if(filtercondition[0] && !o.category.includes(filtercondition[o])) { // checking just the category, but you can check if any of more fields contains the conditions
return false;
}
if(filtercondition[1]) {
for(var key in filtercondition[1]) {
if(filtercondition[1][key] === true && o.acct != key) {
return false;
}
}
}
if(filtercondition[2] && o.transdate < filtercondition[2]) {
return false;
}
if(filtercondition[3] && o.transdate > filtercondition[3]) {
return false;
}
if(filtercondition[4] && o.category !== filtercondition[4]) {
return false;
}
return true;
});
Two notes:
- changed the braces of filtercondition so that it is an array, however I would suggest to use an object instead.
- this {acct1:true,acct2:false,acct3:true...} sample doesn't make sense for me, since it suggests that the acct field should be acct1 and acct3 at the same time.
Create an array of functions, each function representing a condition.
Here's some sample code which demonstrates the approach...
var conditions = [];
// Dynamically build the list of conditions
if(startDateFilter) {
conditions.push(function(item) {
return item.transdate >= startDateFilter.startDate;
});
};
if(categoryFilter) {
conditions.push(function(item) {
return item.cateogry === categoryFilter.category;
});
};
// etc etc
Once you have an array of conditions, you can use Array.prototype.every to run each condition on an item.
var itemsMatchingCondition = data.filter(function(d) {
return conditions.every(function(c) {
return c(d);
});
});
Or, using the more compact arrow functions:
const itemsMatchingCondition = data.filter(d => conditions.every(c => c(d));
First, you'll want to use brackets for your array not curly braces:
var filtercondition = [
"p",
{acct1:true,acct2:false,acct3:true...},
"2016-06-01",
"2016-11-30",
"category3"
];
Then again, I don't think that an array is the best data type for that. Try an object like this:
var filtercondition = {
query: "p",
accounts: {acct1:true,acct2:false,acct3:true...},
date1: "2016-06-01",
date2: "2016-11-30",
category: "category3"
};
Then, try using Array.prototype.filter:
var filtered = data.filter(function(obj) {
for (var key in filtercondition) {
// if condition not met return false
}
return true;
});
I'd go with a bunch of small granular functions and compose them.
//only some utilities, from the top of my mind
var identity = v => v;
//string-related
var string = v => v == null? "": String(v);
var startsWith = needle => haystack => string(haystack).startsWith(needle);
var endsWith = needle => haystack => string(haystack).endsWith(needle);
var contains = needle => haystack => string(haystack).contains(needle);
//do sth with an object
var prop = key => obj => obj != null && prop in obj? obj[prop]: undefined;
var someProp = fn => obj => obj != null && Object.keys(obj).some(k => fn(k) );
var someValue = fn => obj => obj != null && Object.keys(obj).some(k => fn(obj[k]) );
//logic
var eq = b => a => a === b;
var not = fn => function(){ return !fn.apply(this, arguments) };
var and = (...funcs) => funcs.reduce((a, b) => function(){
return a.apply(this, arguments) && b.apply(this, arguments);
});
var or = (...funcs) => funcs.reduce((a, b) => function(){
return a.apply(this, arguments) || b.apply(this, arguments);
});
//composition
var compose = (...funcs) => funcs.reduce((a, b) => v => return a(b(v)));
var chain = (...funcs) => funcs.reduceRight((a, b) => v => return a(b(v)));
//and whatever else you want/need
//but stay granular, don't put too much logic into a single function
and an example composition:
var filterFn = and(
//some value contains "p"
someValue(contains("p")),
//and
chain(
//property "foo"
prop("foo"),
or(
//either contains "asdf"
contains("asdf"),
//or startsWith "123"
startsWith("123")
)
),
)
since I don't know how you build your filterconditions, I cannot tell you exactly how to parse them into such a composition, but you could compose them like this:
//start with something basic, so we don't ever have to check wether filterFn is null
var filterFn = identity;
//and extend/compose it depending on some conditions
if(/*hasQuery*/){
filterFn = and(
// previous filterFn(obj) && some value on obj contains `query`
filterFn,
someValue(contains(query)))
)
}
if(/*condition*/){
//extend filterFn
filterFn = or(
// (obj.foo === null) || previous filterFn(obj)
chain(prop("foo"), eq(null)),
filterFn
);
}
and so on
First, some points:
Your data object is invalid if you're going to use it in the browser. Probably the data comes from MongoDB, right? Your backend (data source) should have a method to encode it properly and remove ObjectID and ISODate references.
Your filtercondition is not a valid JavaScript object/JSON. Check my example.
So, you can filter your data array with Array#filter method.
Something like that:
let data = [{
"_id" : "583f6e6d14c8042dd7c979e6",
"transid" : 1,
"acct" : "acct1",
"transdate" : "2012-01-31T05:00:00.000Z",
"category" : "category1",
"amount" : 103
},
{
"_id" : "583f6e6d14c8042dd7c2132t6",
"transid" : 2,
"acct" : "acct2",
"transdate" : "2012-01-31T05:00:00.000Z",
"category" : "category2",
"amount" : 103
},
{
"_id" : "583f6e6d14c8042dd7c2132t6",
"transid" : 5,
"acct" : "acct2",
"transdate" : "2012-01-31T05:00:00.000Z",
"category" : "category3",
"amount" : 103
}];
let filterToApply = {
acct: {
acct1: true,
acct2: false,
acct3: true
},
initialDate: "2016-06-01",
finalDate: "2016-11-30",
category: "category3"
}
let filterData = (array, filter) => {
return array.filter( (item) => {
/* here, you iterate each item and compare with your filter,
if the item pass, you must return true. Otherwise, false */
/* e.g.: category check (if present only) */
if (filter.category && filter.category !== item.category)
return false;
}
/* add other criterias check... */
return true;
});
}
let dataFiltered = filterData(data, filterToApply);
console.log(dataFiltered);
If you want to filter an array with multiple conditions and the conditions may be optional, then use the following method.
const data = [
{ name: 'John', age: 25, city: 'New York' },
{ name: 'John', age: 25, city: 'New' },
{ name: 'Jane', age: 32, city: 'Los Angeles' },
{ name: 'Bob', age: 45, city: 'New York' },
{ name: 'Alice', age: 38, city: 'Los Angeles' }
];
const filteredData = (n, c, a) => data.filter(item => {
if (n || c || a) {
return (n ? item.name === n : true) && (c ? item.city === c : true) && (a ? item.age === a : true); // keep adding conditons as much as u want
}
});
console.log(filteredData('John', null, 25));
console.log(filteredData(null, 'Los Angeles', 38));
console.log(filteredData(null, 'Los Angeles', null));
You can chain as many as conditions
Related
I have a persons list and I sort it by the column in sortColumn.
const persons = [{
name: "alireza",
family: "seif",
other: {
age: 28,
rate: 30
}
},
{
name: "sara",
family: "niki",
other: {
age: 15,
rate: 15
}
},
{
name: "fateme",
family: "azizy",
other: {
age: 27,
rate: 35
}
}
];
const sortColumn = {
path: "name",
order: "asc"
};
persons.sort((person1, person2) =>
person1[sortColumn.path] > person2[sortColumn.path] ?
sortColumn.order === "asc" ?
1 :
-1 :
person2[sortColumn.path] > person1[sortColumn.path] ?
sortColumn.order === "asc" ?
-1 :
1 :
0
);
console.log(persons);
If sortColumn.path is "name" and order is "asc" (or "desc"), the sort function works correctly. But how can I sort by "other.age"?
Thanks.
You could take a functin which return a sort function, depending on the sort order.
This sorting function uses another function for getting a value from an object by reducing the splitted path to the value.
const
sortBy = ({ order = 'asc', path }) => order === 'asc'
? (a, b) => ((a, b) => a > b || -(a < b))(getValue(a, path), getValue(b, path))
: (a, b) => ((a, b) => b > a || -(b < a))(getValue(a, path), getValue(b, path)),
getValue = (object, keys) => keys.split('.').reduce((o, k) => o[k], object),
persons = [{ name: "sara", family: "niki", other: { age: 15, rate: 15 } }, { name: "alireza", family: "seif", other: { age: 28, rate: 30 } }, { name: "fateme", family: "azizy", other: { age: 27, rate: 35 } }];
console.log(persons.sort(sortBy({ path: "name", order: "asc" })));
console.log(persons.sort(sortBy({ path: "other.rate", order: "desc" })));
.as-console-wrapper { max-height: 100% !important; top: 0; }
If you want to do sort by that deep property age, you can't use sortColumn exactly as you have... Instead, one option is to modify it by making it an array of properties, like so:
sortColumn = { path:["other","age"], order:"asc" }
This way, you'd also have to modify the sort function - as seen in the example below:
const persons = [
{name:"alireza",family:"seif",other:{age:28,rate:30}},
{name:"fateme",family:"azizy",other:{age:27,rate:35}},
{name:"sara",family:"niki",other:{age:15,rate:15}}
]
const sortColumn = { path:["other","age"], order:"asc" }
persons.sort((person1, person2) =>
person1[sortColumn.path[0]][sortColumn.path[1]] > person2[sortColumn.path[0]][sortColumn.path[1]]
? sortColumn.order === "asc"
? 1
: -1
: person2[sortColumn.path[0]][sortColumn.path[1]] > person1[sortColumn.path[0]][sortColumn.path[1]]
? sortColumn.order === "asc"
? -1
: 1
: 0
);
console.log(persons)
However, this approach doesn't work to sort by "name" since this sort function sorts your data by some piece of data that is two-layers deep (inside "other", then "age"). Here's a modification you can make to the sort function which lets you sort by any properties, any number of layers deep into your data:
const persons = [
{name:"alireza",family:"seif",other:{age:28,rate:30}},
{name:"fateme",family:"azizy",other:{age:27,rate:35}},
{name:"sara",family:"niki",other:{age:15,rate:15}}
]
const sortColumn = { path:["name"], order:"asc" }
persons.sort((person1, person2) => {
// get array of paths
const sortPaths = sortColumn.path;
// get values to sort by
const val1 = sortPaths.reduce((acc, path) => {
if (acc[path]) return acc[path]
else alert(`can't find prop ${path} in person1`);
}, person1)
const val2 = sortPaths.reduce((acc, path) => {
if (acc[path]) return acc[path]
else alert(`can't find prop ${path} in person2`);
}, person2)
return val1 > val2
? sortColumn.order === "asc"
? 1
: -1
: val2 > val1
? sortColumn.order === "asc"
? -1
: 1
: 0
});
console.log(persons)
https://stackoverflow.com/questions/59792589/sort-object-in-object-by-javascript/59792918#
As you can see in this second snippet, you can now search by a shallow property "name" by using path: ["name"], but if you want to sort by a deep value, just add both properties to the path array like this: path: ["other", "age"]
Hope this helps!
The main thing to do is to make your code expect 'path' be a function that selects a property's value, instead of a string pointing to a property name. That way it's much more flexible.
const sortColumn = {
path: p => p.other.age,
order: 'desc'
};
However, if 'persons' is not the only object you'd like to do this with, you can further abstract such a function for general use with any array, such as this:
function sorter (array, path, order) {
array.sort((a,b) => {
let result =
path(a) > path(b) ? 1
: path(a) < path(b) ? -1
: 0;
if (order === "desc")
result = -result;
return result;
});
}
Use it like this:
sorter(persons, p => p.other.age, 'desc');
Expand and run the snippet below to see it in action:
function sorter (array, path, order) {
array.sort((a,b) => {
let result =
path(a) > path(b) ? 1
: path(a) < path(b) ? -1
: 0;
if (order === "desc")
result = -result;
return result;
});
}
const persons = [
{name: "alireza", family: "seif", other: {age: 28, rate: 30}},
{name: "sara", family: "niki", other: {age: 15, rate: 15}},
{name: "fateme", family: "azizy", other: {age: 27, rate: 35}}
];
// convenience function
let sortAndLog = (array, path, order) => {
sorter(array, path, order);
console.log(array.map(path));
}
sortAndLog(persons, p => p.name, "asc");
sortAndLog(persons, p => p.name, "desc");
sortAndLog(persons, p => p.other.age, "asc");
sortAndLog(persons, p => p.other.age, "desc");
i have 3 objects having same data but inside array having separate service and offer id so i tried to get expected result as below mentioned and please check my try here . Thanks in advance
Object 1:
const obj1 = {
bid : 1,
mobile : 9533703390,
services : [
{
service_id : 5,
offer_id : 10,
count : 1
}
]
}
object2 :
const obj2 = {
bid : 1,
mobile : 9524703390,
services : [
{
service_id : 8,
offer_id : 12,
count : 1
}
]
}
object 3:
const obj3 = {
bid : 1,
mobile : 9524703390,
services : [
{
service_id : 5,
offer_id : 10,
count : 1
}
]
}
Final Result - each object having separate services and offer then if same offerid & serviceid came need to add count + 1 otherwise return data
const result = {
bid : 1,
mobile : 9524703390,
services : [
{
service_id : 5,
offer_id : 10,
count : 2
},
{
service_id : 8,
offer_id : 12,
count : 1
}
]
}
You can use array#reduce to merge all objects into single object and array#concat the services values. Then use array#reduce to merge all service object based on service_id in an object and reassign the values of this object to services.
const obj1 = { bid : 1, mobile : 9533703390, services : [ { service_id : 5, offer_id : 10, count : 1 } ] },
obj2 = { bid : 1, mobile : 9524703390, services : [ { service_id : 8, offer_id : 12, count : 1 } ] },
obj3 = { bid : 1, mobile : 9524703390, services : [ { service_id : 5, offer_id : 12, count : 1 } ] };
var combined = [obj1, obj2, obj3].reduce((r,o) => Object.assign({}, o, {services : r.services.concat(o.services)}));
combined.services = Object.values(combined.services.reduce((res, services) => {
if(res[services.service_id])
res[services.service_id].count += services.count;
else
res[services.service_id] = Object.assign({}, services);
return res;
},{}));
console.log(combined)
The spread operator doesn't do recursive appending or anything like that. You can however use it in conjunction with Object.assign like so:
const result = Object.assign(
obj1,
obj2,
obj3, {
services: [ ...obj1.services, ...obj2.services, ...obj3.services, ]
}); //Consolidate everything
Then you can consolidate the services:
const servicesObject = {};
result.services.forEach((service) => {
if (servicesObject[service.service_id] !== undefined) {
servicesObject[service.service_id].count += 1;
} else {
servicesObject[service.service_id] = service;
}
}); // Merge services
result.services = servicesObject;
If you still want the services to be an array then you can do
result.services = Object.entries(servicesObject)
.map(([key,value]) => value);
Check the updated fiddle http://jsfiddle.net/rkdejpab/15/
function merge(...objs) {
let result = objs.reduce((acc, item) => {
acc.bid = item.bid;
acc.mobile = item.mobile;
if (!acc.services) {
acc.services = []
acc.services.push(item.services[0]);
}
else {
let index = acc.services.findIndex(function (elem) {
return elem.service_id === item.services[0].service_id && elem.offer_id == item.services[0].offer_id;
});
if (!(index === -1)) {
acc.services[index].count += 1;
}
else {
acc.services.push(item.services[0]);
}
}
return acc
}, {});
return result;
}
console.log(merge(obj1, obj2, obj3));
I have to compare some JSON data and return index of position. I use pure JavaScript.
I have data below:
NAMES
[
{
"someName" : Name1,
"secondData" : "aaaa1",
"thirdData" : bbbb1
},
{
"someName" : Name2,
"secondData" : "aaaa2",
"thirdData" : bbbb2
},
{
"someName" : Name3,
"secondData" : "aaaa3",
"thirdData" : bbbb3
},
{
"someName" : Name4,
"secondData" : "aaaa4",
"thirdData" : bbbb4
}
]
and JSON SEATS
[
{
"seats" : 0,
"someName" : "Name4",
omeData" : null,
"someData" : null
},
{
"seats" : 1,
"someName" : "Name3",
"someData" : null,
"someData" : null
},
{
"seats" : 2,
"someName" : "Name1",
"someData" : null,
"someData" : null
},
{
"seats" : 3,
"someName" : "Name2",
"someData" : null,
"someData" : null
}
]
All what I want to do is compare this JSON like this:
Take someName from NAMES.someName and search the same name in SEATS.someName if is the same create new array RESULTS. Index in RESULTS array shuldbe SEATS.seats and data from NAMES.
Example below
RESULTS[0] = NAMES[{"someName" : Name4,"secondData" : "aaaa4","thirdData" : bbbb4}]
RESULTS[1] = NAMES[{"someName" : Name3,"secondData" : "aaaa3","thirdData" : bbbb3}]
RESULTS[2] = NAMES[{"someName" : Name1,"secondData" : "aaaa1","thirdData" : bbbb1}]
RESULTS[3] = NAMES[{"someName" : Name2,"secondData" : "aaaa2","thirdData" : bbbb2}]
I start do this like this but I stack
for(i=0;i<=459; i++) {
if(mergeData[i][2] == jsonData[4].rows[i].find(compareElement)) {
}
}
function compareElement(element) {
return element.someName == i;
}
Problem is if I use find like this I have some error and program stop I can't find way how to solve this.
var result = [];
NAMES.forEach(function(name) {
var found = SEATS.find(function(seat) {
return name.someName === seat.someName
});
if (found) {
result[found.seats] = name;
}
});
This solution works for both Objects as well as Arrays.
function compare(obj: any, obj2: any): boolean {
if (typeof obj !== typeof obj2) {
return false;
}
if (typeof obj !== "object" && typeof obj2 !== "object") {
return obj === obj2;
} else {
for (let key in obj) {
if (key) {
return compare(obj[key], obj2[key]);
}
}
return false;
}
}
This question is for purely for learning purposes. funfunfunction on youtube says that
Any list higher order list transformation can be written in Array.reduce()
Audio/video Reference: https://youtu.be/Wl98eZpkp-c?t=138.
Question:
Purely for learning how would one rewrite Array.every() with Array.reduce()
This question stems from my previous question here
Javascript Example:
var approved1 = [
{
dateApproved: new Date(),
id: 1,
},
{
dateApproved: new Date(),
id: 2,
}
];
var approved2 = [
{
dateApproved: null,
id: 1,
},
{
dateApproved: new Date(),
id: 2,
}
];
approved1.every(a => a.dateApproved != null) ? 'APPROVED' : 'PENDING'
// 'APPROVED'
approved2.reduce(every) ? 'APPROVED' : 'PENDING'
// 'PENDING'
I struggle with where I store the currently passed values. Where do I store the "passed" values like Array.every() does?
function every(previousValue, currentValue, currentIdx, arr) {
if(previousValue.dateApproved !== null && currentValue.dateApproved !== null) {
return currentValue;
}
}
You can use reduce instead of every and make it work, but I'd suggest you to use them in there apt places. Both have distinctive requirement.
array.reduce
array.reduce(callback(curentElement, nextElement, index, array),[initialCurrentElement])
Array.reduce has 4 args.
currentElement: By default, this will be 1st element in array for 1st iteration and then, this variable will hold value that you return. If an initial value is passed, then it will hold that and start from there.
nextElement: By default it holds second or next element. If initial value is passed, this will hold first value.
index: this holds the index of current element.
array: This is the parent array on which we are looping.
initialCurrentElement: This is an optional argument. If this is passed, looping starts with this.
Following is a sample showing an illustration:
Note:
Array.every will break on first falsey condition. Array.reduce will not.
Array.reduce is meant to compare 2 values of same array where as Array.every is meant to compare each values to an expression. Using .reduce instead of .every is just an overkill.
var approved2 = [{
dateApproved: null,
id: 1,
}, {
dateApproved: new Date(),
id: 2,
}];
var everyResult = approved2.every(x => {
console.log(x.dateApproved)
x.dateApproved !== null
})
console.log(everyResult)
var reduceResult = approved2.reduce((p, c) => {
console.log(c.dateApproved)
return !p ? p : c.dateApproved !== null
}, true)
console.log(reduceResult? 'Approved': 'Rejected')
This should do the trick:
function every(pre, curr) {
return pre.dateApproved != null && curr.dateApproved != null
}
approved1.reduce(every) ? 'APPROVED' : 'PENDING' // APPROVED
approved2.reduce(every) ? 'APPROVED' : 'PENDING' // PENDING
And I'm pretty sure you can do it without curr, just pre.
var status = approved1.reduce( val => (val.dateApproved) ? 'APPROVED': 'REJECTED')
var approved1 = [
{
dateApproved: new Date(),
id: 1,
},
{
dateApproved: new Date(),
id: 2,
}
];
var approved2 = [
{
dateApproved: new Date(),
id: 1,
},
{
dateApproved: null,
id: 2,
},
{
dateApproved: new Date(),
id: 2,
}
];
console.log(approved2.reduce( (prev, curr) => (prev.dateApproved && curr.dateApproved) ? true : false) ? 'APPROVED':'REJECTED')
console.log(approved1.reduce( (prev, curr) => (prev.dateApproved && curr.dateApproved) ? true : false) ? 'APPROVED':'REJECTED')
You might roughly implement it as folows
Array.prototype.every = function(cb){
return this.reduce((p,c,i,a) => i === 1 ? cb(p,i-1,a) && cb(c,i,a)
: p && cb(c,i,a));
};
var arr = [9,2,3,9,12,5],
brr = [1,2,3,4,5,6,9];
console.log(arr.every(e => e < 10));
console.log(brr.every(e => e < 10));
I have this array of objects.
[Object, Object, Object]
0:Object
name: "Rick"
Contact: "Yes"
Date:'null'
Location:'null'
1:Object
name:"Anjie"
Contact:"No"
Date:'13/6/2016'
Location:'LA'
2:Object
name:"dillan"
Contact:"Maybe"
Date:'17/6/2016'
Location:'NY'
As you can see, there are null values for Object[0] for Date and Location. I want to check if there is a null value present in the entire array of Objects.
If there is a null value present for 'Date' and 'Location', i should be able to display 'Null present' at the console. If no null values are present, it should display 'Data right' at the console.
can someone please let me know how to achieve this.
var wasNull = false;
for(var i in objectsArray) {
if(objectsArray[i].Date == null || objectsArray[i].Location == null) wasNull = true;
}
if(wasNull) console.log('Was null');
else console.log('Data right');
Do it using Object.keys() and Array#some methods
var data = [{
name: "Rick",
Contact: "Yes",
Date: null,
Location: null
}, {
name: "Anjie",
Contact: "No",
Date: '13/6/2016',
Location: 'LA'
}, {
name: "dillan",
Contact: "Maybe",
Date: '17/6/2016',
Location: 'NY'
}];
// iterate over array elements
data.forEach(function(v, i) {
if (
// get all properties and check any of it's value is null
Object.keys(v).some(function(k) {
return v[k] == null;
})
)
console.log('null value present', i);
else
console.log('data right', i);
});
Use some() and check if there is a null.
var arr = [
{ a : "a", b : "b", c : "c" },
{ a : "a", b : "b", c : "c" },
{ a : "a", b : "b", c : null }
];
function hasNull(element, index, array) {
return element.a===null || element.b===null || element.c===null;
}
console.log( arr.some(hasNull) );
If you do not want to hardCode the if, than you need to add another loop and loop over the keys.
var arr = [
{ a : "a1", b : "b1", c : "c1" },
{ a : "a2", b : "b2", c : "c2" },
{ a : "a3", b : "b3", c : null }
];
function hasNull(element, index, array) {
return Object.keys(element).some(
function (key) {
return element[key]===null;
}
);
}
console.log( arr.some(hasNull) );
or JSON with a reg exp (
var arr = [
{ a : "a1", b : "b1", c : "c1" },
{ a : "a2", b : "b2", c : "c2" },
{ a : "a3", b : "b3", c : null }
];
var hasMatch = JSON.stringify(arr).match(/:null[\},]/)!==null;
console.log(hasMatch);
A solution using underscore:
var nullPresent = _.some(data, item => _.some(_.pick(item, 'Date', 'Location'), _.isNull));