how to use .include() method to check the value which is in a json inside array - javascript

I want to compare the value of a particular key in my JSON array with new value to check whether the value exists or not.
For example, I have an array:
[
{ name: abc, num: 121212 },
{ name: bcd, num: 21212 },
{ name: def, num: 111222 }
]
Now a new value comes which I want to check. Does that name already exist? If it does, then I only want to update the number and if not then I want to push the object in the array.
Here is my code:
if ((Dnum.num).includes(number)) {
console.log("inside if");
console.log(Dnum.indexOf(number));
} else {
Dnum.push({num:number,
lat:lat,
lng:lng,
name:name
});
}

Well, your problem (if I understand correctly) is that you want to use includes() but what you actually want to accomplish doesn't correspond to what the method does. You want to find if there's an object with a certain name in your array already, not if it contains a known element. Something like this:
var data = [{name: 'abc', num: 121212}, {name: 'bcd', num: 21212}, {name: 'def', num: 111222}];
function addOrUpdate(newElement, data) {
var i;
for (i = 0; i < data.length; i++) {
if (data[i].name == newElement.name) {
data[i] = newElement;
return;
}
}
data.push(newElement);
}
addOrUpdate({name: 'bcd', num: 131313}, data);
console.log(data);
addOrUpdate({name: 'new', num: 131313}, data);
console.log(data);

Problem:
Actually .includes() and .indexOf() methods won't work with objects, they should be used with an array of strings or Numbers as they use strict equality to compare the elements and objects can't be compared this way, so you need to implement this logic by yourself.
Solution:
You need to check if an object matching the searched name already exists in the array, update the num value of this object, otherwise if no object matches the searched name, push the new object to the array:
if (arr.some(function(obj) {
return obj.name === searchedVal.name;
})) {
arr.forEach(function(el, index) {
if (el.name === searchedVal.name) {
el.num += searchedVal.num;
found = true;
}
});
} else {
arr.push(searchedVal);
}
Demo:
var arr = [{
name: "abc",
num: 121212
}, {
name: "bcd",
num: 21212
}, {
name: "def",
num: 111222
}];
var searchedVal = {
name: "abc",
num: 5
};
if (arr.some(function(obj) {
return obj.name === searchedVal.name;
})) {
arr.forEach(function(el, index) {
if (el.name === searchedVal.name) {
el.num += searchedVal.num;
found = true;
}
});
} else {
arr.push(searchedVal);
}
console.log(arr);
If you don't want to use .some() method, you can do it this way:
var searchedVal = {
name: "abc",
num: 5
};
var found = false;
arr.forEach(function(el, index) {
if (el.name === searchedVal.name) {
el.num+= searchedVal.num;
found = true;
}
});
if (!found) {
arr.push(searchedVal);
}

Use Array.prototype.find():
var res = Dnum.find(function (item) {
return item.num === number;
});
if (res) {
console.log("inside if");
console.log(res);
res.num = number;
} else {
Dnum.push({
num:number,
lat:lat,
lng:lng,
name:name
});
}

Related

what can i do i got out when i am searching class then count how many student in class

let student = [{
id:1,
name:'aman',
class:'10',
gender:'male'
},{
id:2,
name:'shivani',
class:'10',
gender:'female'
},{
id:2,
name:'riyan',
class:'11',
gender:'female'
}]
function customFilter(objList, text){
if(undefined === text || text === '' ) return objList;
return objList.filter(product => {
let flag;
for(let prop in product){
if(product[prop].toString().indexOf(text)>-1){
product[prop] = 0
product[prop]++
flag = product[prop]
console.log(flag)
}
}
return flag;
});}
console.log( customFilter(student, '10'))
I want the output of the number of students in a class. Example: when I pass class 10 as an argument then i should get output how many students in class 10
output:
{class:10,stduent:5 }
I didn't get your question well, but I assumed you want number of student in a class like this {class:10, students: 2}
let student = [
{ id:1, name:'aman', class:'10', gender:'male'},
{ id:2, name:'shivani', class:'10', gender:'female' },
{ id:3, name:'riyan', class:'11', gender:'female' }
]
function customFilter(objList, text){
if(undefined === text || text === '' ) return objList;
const numberOfStudents = objList.filter(product => {
for (let prop in product) {
if (product[prop].toString().includes(text)) {
return true;
}
}
});
return {class:text, student:numberOfStudents.length }
}
console.log( customFilter(student, '10'))
If that's the case this code will do , hope it helps
This would also work:
let students = [
{ id: 1, name: "aman", class: "10", gender: "male" },
{ id: 2, name: "shivani", class: "10", gender: "female" },
{ id: 2, name: "riyan", class: "11", gender: "female" },
];
const customFilter = (students, key, value) => {
const res = { [key]: value, student: 0 };
students.forEach((student) => {
if (student[key] === value) {
res.student += 1;
}
});
return res;
};
console.log(customFilter(students, "class", "10"));
Using Array.prototype.forEach()
There are few problems with the code. change class:'10' to grade: 10,.
don't use "class" as a variable name. might cause a few errors
There is a missing ,
numbers shouldn't be inside quotes because the number will be stored as a string
let student = [
{ id: 1, name: 'aman', grade: 10, gender: 'male'},
{ id: 2, name: 'shivani', grade: 10, gender: 'female' },
{ id: 2, name: 'riyan', grade: 11, gender: 'female' },
]
function customFilter(objList, value){
if(!value || value === '') return objList;
let count = 0
objList.forEach(obj => {
const { grade } = obj;
if(grade === value){
count++;
}
})
return {grade: 10, count};
}
console.log(customFilter(student, 10));
and forEach can be used instead of filter. It loops from start to end of an array
Use .reduce() to group all objects that match.
/* hits (accumulator) is initially an empty array.
now (current) is the object of the current iteration. */
array.reduce((hits, now) => { //...
On each iteration, get all of the current object's values (in lower case) in an array.
Object.values(now).map(val => val.toLowerCase())
/* result of the first object: ["01gn3z1ryjjqhn588ax3bws6qb", "theo bramstom",
"genderqueer", "english"] */
If any of the values of the current object matches the given string (term), add the current object to the hits array.
if (Object.values(now)
.map(val => val.toLowerCase()).includes(term.toLowerCase())) {
hits.push(now);
}
An object literal is returned.
{
"matches": /* an array of all matched objects */,
"total": /* the .length of "matches" array */
};
/* To get the answer prompted in OP -- do the following */
const x = dataFilter(students, "Math");
console.log(x.total);
// NOTE: key "class" is now "subject" just for aesthetics
const students=[{id:"01GN3Z1RYJJQHN588AX3BWS6QB",name:"Theo Bramstom",gender:"Genderqueer",subject:"English"},{id:"01GN3Z1RYM527HAX56ZN14F0YB",name:"Juli Marsy",gender:"Female",subject:"History"},{id:"01GN3Z1RYPYP1FFFEY55T92VX2",name:"Linc Espley",gender:"Non-binary",subject:"Math"},{id:"01GN3Z1RYR325M0QETVVPE2N5J",name:"Barbabas Grisley",gender:"Male",subject:"Math"},{id:"01GN3Z1RYTXA49SBQYXR9DMC04",name:"Godfree Braybrook",gender:"Male",subject:"English"},{id:"01GN3Z1RYVE4N5D16C8QWB1XGF",name:"Jason De Vuyst",gender:"Male",subject:"History"},{id:"01GN3Z1RYXY9WXF1Y407HXFYH8",name:"Adler McCanny",gender:"Male",subject:"Math"},{id:"01GN3Z1RYY9XV444J0SP5Y0QC2",name:"Noellyn MacMorland",gender:"Genderqueer",subject:"Math"},{id:"01GN3Z1RZ0HPQNZ1VKX8ZHA9ZY",name:"Padget Geldeford",gender:"Male",subject:"Math"},
{id:"01GN3Z1RZ2DZE92NG42KSGDXN9",name:"Milissent Treby",gender:"Female",subject:"Art"}];
const dataFilter = (array, term) => {
let result = array.reduce((hits, now) => {
if (Object.values(now).map(val => val.toLowerCase()).includes(term.toLowerCase())) {
hits.push(now);
}
return hits;
}, []);
return {"matches": result, "total": result.length};
}
console.log(dataFilter(students, "Math"));
// Control case: term === "Math"
console.log(dataFilter(students, "PE"));
// No match case: term != "PE"
console.log(dataFilter(students, "female"));
// Case insensitive case: term === "Female"

Find Duplicate Array By Caption without using multiple loops [duplicate]

I need some help with iterating through array, I keep getting stuck or reinventing the wheel.
values = [
{ name: 'someName1' },
{ name: 'someName2' },
{ name: 'someName1' },
{ name: 'someName1' }
]
How could I check if there are two (or more) same name value in array? I do not need a counter, just setting some variable if array values are not unique. Have in mind that array length is dynamic, also array values.
Use array.prototype.map and array.prototype.some:
var values = [
{ name: 'someName1' },
{ name: 'someName2' },
{ name: 'someName4' },
{ name: 'someName2' }
];
var valueArr = values.map(function(item){ return item.name });
var isDuplicate = valueArr.some(function(item, idx){
return valueArr.indexOf(item) != idx
});
console.log(isDuplicate);
ECMA Script 6 Version
If you are in an environment which supports ECMA Script 6's Set, then you can use Array.prototype.some and a Set object, like this
let seen = new Set();
var hasDuplicates = values.some(function(currentObject) {
return seen.size === seen.add(currentObject.name).size;
});
Here, we insert each and every object's name into the Set and we check if the size before and after adding are the same. This works because Set.size returns a number based on unique data (set only adds entries if the data is unique). If/when you have duplicate names, the size won't increase (because the data won't be unique) which means that we would have already seen the current name and it will return true.
ECMA Script 5 Version
If you don't have Set support, then you can use a normal JavaScript object itself, like this
var seen = {};
var hasDuplicates = values.some(function(currentObject) {
if (seen.hasOwnProperty(currentObject.name)) {
// Current name is already seen
return true;
}
// Current name is being seen for the first time
return (seen[currentObject.name] = false);
});
The same can be written succinctly, like this
var seen = {};
var hasDuplicates = values.some(function (currentObject) {
return seen.hasOwnProperty(currentObject.name)
|| (seen[currentObject.name] = false);
});
Note: In both the cases, we use Array.prototype.some because it will short-circuit. The moment it gets a truthy value from the function, it will return true immediately, it will not process rest of the elements.
In TS and ES6 you can create a new Set with the property to be unique and compare it's size to the original array.
const values = [
{ name: 'someName1' },
{ name: 'someName2' },
{ name: 'someName3' },
{ name: 'someName1' }
]
const uniqueValues = new Set(values.map(v => v.name));
if (uniqueValues.size < values.length) {
console.log('duplicates found')
}
To know if simple array has duplicates we can compare first and last indexes of the same value:
The function:
var hasDupsSimple = function(array) {
return array.some(function(value) { // .some will break as soon as duplicate found (no need to itterate over all array)
return array.indexOf(value) !== array.lastIndexOf(value); // comparing first and last indexes of the same value
})
}
Tests:
hasDupsSimple([1,2,3,4,2,7])
// => true
hasDupsSimple([1,2,3,4,8,7])
// => false
hasDupsSimple([1,"hello",3,"bye","hello",7])
// => true
For an array of objects we need to convert the objects values to a simple array first:
Converting array of objects to the simple array with map:
var hasDupsObjects = function(array) {
return array.map(function(value) {
return value.suit + value.rank
}).some(function(value, index, array) {
return array.indexOf(value) !== array.lastIndexOf(value);
})
}
Tests:
var cardHand = [
{ "suit":"spades", "rank":"ten" },
{ "suit":"diamonds", "rank":"ace" },
{ "suit":"hearts", "rank":"ten" },
{ "suit":"clubs", "rank":"two" },
{ "suit":"spades", "rank":"three" },
]
hasDupsObjects(cardHand);
// => false
var cardHand2 = [
{ "suit":"spades", "rank":"ten" },
{ "suit":"diamonds", "rank":"ace" },
{ "suit":"hearts", "rank":"ten" },
{ "suit":"clubs", "rank":"two" },
{ "suit":"spades", "rank":"ten" },
]
hasDupsObjects(cardHand2);
// => true
if you are looking for a boolean, the quickest way would be
var values = [
{ name: 'someName1' },
{ name: 'someName2' },
{ name: 'someName1' },
{ name: 'someName1' }
]
// solution
var hasDuplicate = false;
values.map(v => v.name).sort().sort((a, b) => {
if (a === b) hasDuplicate = true
})
console.log('hasDuplicate', hasDuplicate)
const values = [
{ name: 'someName1' },
{ name: 'someName2' },
{ name: 'someName4' },
{ name: 'someName4' }
];
const foundDuplicateName = values.find((nnn, index) =>{
return values.find((x, ind)=> x.name === nnn.name && index !== ind )
})
console.log(foundDuplicateName)
Found the first one duplicate name
const values = [
{ name: 'someName1' },
{ name: 'someName2' },
{ name: 'someName4' },
{ name: 'someName4' }
];
const foundDuplicateName = values.find((nnn, index) =>{
return values.find((x, ind)=> x.name === nnn.name && index !== ind )
})
You just need one line of code.
var values = [
{ name: 'someName1' },
{ name: 'someName2' },
{ name: 'someName4' },
{ name: 'someName2' }
];
let hasDuplicates = values.map(v => v.name).length > new Set(values.map(v => v.name)).size ? true : false;
Try an simple loop:
var repeat = [], tmp, i = 0;
while(i < values.length){
repeat.indexOf(tmp = values[i++].name) > -1 ? values.pop(i--) : repeat.push(tmp)
}
Demo
With Underscore.js A few ways with Underscore can be done. Here is one of them. Checking if the array is already unique.
function isNameUnique(values){
return _.uniq(values, function(v){ return v.name }).length == values.length
}
With vanilla JavaScript
By checking if there is no recurring names in the array.
function isNameUnique(values){
var names = values.map(function(v){ return v.name });
return !names.some(function(v){
return names.filter(function(w){ return w==v }).length>1
});
}
//checking duplicate elements in an array
var arr=[1,3,4,6,8,9,1,3,4,7];
var hp=new Map();
console.log(arr.sort());
var freq=0;
for(var i=1;i<arr.length;i++){
// console.log(arr[i-1]+" "+arr[i]);
if(arr[i]==arr[i-1]){
freq++;
}
else{
hp.set(arr[i-1],freq+1);
freq=0;
}
}
console.log(hp);
You can use map to return just the name, and then use this forEach trick to check if it exists at least twice:
var areAnyDuplicates = false;
values.map(function(obj) {
return obj.name;
}).forEach(function (element, index, arr) {
if (arr.indexOf(element) !== index) {
areAnyDuplicates = true;
}
});
Fiddle
Adding updated es6 function to check for unique and duplicate values in array. This function is modular and can be reused throughout the code base. Thanks to all the post above.
/* checks for unique keynames in array */
const checkForUnique = (arrToCheck, keyName) => {
/* make set to remove duplicates and compare to */
const uniqueValues = [...new Set(arrToCheck.map(v => v[keyName]))];
if(arrToCheck.length !== uniqueValues.length){
console.log('NOT UNIQUE')
return false
}
return true
}
let arr = [{name:'joshua'},{name:'tony'},{name:'joshua'}]
/* call function with arr and key to check for */
let isUnique = checkForUnique(arr,'name')
checkDuplicate(arr, item) {
const uniqueValues = new Set(arr.map((v) => v[item]));
return uniqueValues.size < arr.length;
},
console.log(this.checkDuplicate(this.dutyExemptionBase, 'CI_ExemptionType')); // true || false
It is quite interesting to work with arrays
You can use new Set() method to find duplicate values!
let's assume you have an array of objects like this...
let myArray = [
{ id: 0, name: "Jhon" },
{ id: 1, name: "sara" },
{ id: 2, name: "pop" },
{ id: 3, name: "sara" }
]
const findUnique = new Set(myArray.map(x => {
return x.name
}))
if(findUnique.size < myArray.length){
console.log("duplicates found!")
}else{
console.log("Done!")
}
const duplicateValues = [{ name: "abc" }, { name: "bcv" }, { name: "abc" }];
const isContainDuplicate = (params) => {
const removedDuplicate = new Set(params.map((el) => el.name));
return params.length !== removedDuplicate.size;
};
const isDuplicate = isContainDuplicate(duplicateValues);
console.log("isDuplicate");

New array of objects by comparing and pushing unique objects

I have 2 arrays of objects exclude and people, I want to create a new object by checking exclude properties against people properties and only adding objects in people that don't feature in exclude. So far my attempt is a little wild and wondering if someone can help make things a little better or offer a nicer solution?
Fiddle http://jsfiddle.net/kyllle/k02jw2j0/
JS
var exclude = [{
id: 1,
name: 'John'
}];
var peopleArr = [{
id: 1,
name: 'John'
}, {
id: 2,
name: 'James'
}, {
id: 3,
name: 'Simon'
}];
var myObj = [];
for (key in peopleArr) {
for (k in exclude) {
if (JSON.stringify(peopleArr[key]) != JSON.stringify(exclude[k])) {
console.log(peopleArr[key]);
myObj.push(peopleArr[key]);
}
}
}
console.log(myObj);
Under the assumption that exclude can have multiple items, I would use a combination of filter() and forEach() :
var newArray = peopleArr.filter(function(person) {
include = true;
exclude.forEach(function(exl) {
if (JSON.stringify(exl) == JSON.stringify(person)) {
include = false;
return;
}
})
if (include) return person;
})
forked fiddle -> http://jsfiddle.net/6c24rte8/
You repeat some JSON.stringify calls.
You can convert your arrays to JSON once, and then reuse it. Also, you can replace your push by Array.prototype.filter.
var excludeJson = exclude.map(JSON.stringify);
peopleArr = peopleArr.filter(function(x) {
return excludeJson.indexOf(JSON.stringify(x)) === -1;
});
Here is the working snippet:
var exclude = [{
id: 1,
name: 'John'
}];
var peopleArr = [{
id: 1,
name: 'John'
}, {
id: 2,
name: 'James'
}, {
id: 3,
name: 'Simon'
}];
var excludeJson = exclude.map(JSON.stringify);
peopleArr = peopleArr.filter(function(x) {
return excludeJson.indexOf(JSON.stringify(x)) === -1;
});
document.body.innerText = JSON.stringify(peopleArr);
This can be achieved with .filter and .findIndex
var myObj = peopleArr.filter(function(person){
var idx = exclude.findIndex(function(exc) { return person.id == exc.id && person.name == exc.name; });
return idx == -1; // means current person not found in the exclude list
});
I have explicitly compared the actual properties back to the original, there is nothing particularly wrong with your original way of comparing the stringified version (JSON.stringify(e) == JSON.stringify(x) could be used in my example)

How can I check if the array of objects have duplicate property values?

I need some help with iterating through array, I keep getting stuck or reinventing the wheel.
values = [
{ name: 'someName1' },
{ name: 'someName2' },
{ name: 'someName1' },
{ name: 'someName1' }
]
How could I check if there are two (or more) same name value in array? I do not need a counter, just setting some variable if array values are not unique. Have in mind that array length is dynamic, also array values.
Use array.prototype.map and array.prototype.some:
var values = [
{ name: 'someName1' },
{ name: 'someName2' },
{ name: 'someName4' },
{ name: 'someName2' }
];
var valueArr = values.map(function(item){ return item.name });
var isDuplicate = valueArr.some(function(item, idx){
return valueArr.indexOf(item) != idx
});
console.log(isDuplicate);
ECMA Script 6 Version
If you are in an environment which supports ECMA Script 6's Set, then you can use Array.prototype.some and a Set object, like this
let seen = new Set();
var hasDuplicates = values.some(function(currentObject) {
return seen.size === seen.add(currentObject.name).size;
});
Here, we insert each and every object's name into the Set and we check if the size before and after adding are the same. This works because Set.size returns a number based on unique data (set only adds entries if the data is unique). If/when you have duplicate names, the size won't increase (because the data won't be unique) which means that we would have already seen the current name and it will return true.
ECMA Script 5 Version
If you don't have Set support, then you can use a normal JavaScript object itself, like this
var seen = {};
var hasDuplicates = values.some(function(currentObject) {
if (seen.hasOwnProperty(currentObject.name)) {
// Current name is already seen
return true;
}
// Current name is being seen for the first time
return (seen[currentObject.name] = false);
});
The same can be written succinctly, like this
var seen = {};
var hasDuplicates = values.some(function (currentObject) {
return seen.hasOwnProperty(currentObject.name)
|| (seen[currentObject.name] = false);
});
Note: In both the cases, we use Array.prototype.some because it will short-circuit. The moment it gets a truthy value from the function, it will return true immediately, it will not process rest of the elements.
In TS and ES6 you can create a new Set with the property to be unique and compare it's size to the original array.
const values = [
{ name: 'someName1' },
{ name: 'someName2' },
{ name: 'someName3' },
{ name: 'someName1' }
]
const uniqueValues = new Set(values.map(v => v.name));
if (uniqueValues.size < values.length) {
console.log('duplicates found')
}
To know if simple array has duplicates we can compare first and last indexes of the same value:
The function:
var hasDupsSimple = function(array) {
return array.some(function(value) { // .some will break as soon as duplicate found (no need to itterate over all array)
return array.indexOf(value) !== array.lastIndexOf(value); // comparing first and last indexes of the same value
})
}
Tests:
hasDupsSimple([1,2,3,4,2,7])
// => true
hasDupsSimple([1,2,3,4,8,7])
// => false
hasDupsSimple([1,"hello",3,"bye","hello",7])
// => true
For an array of objects we need to convert the objects values to a simple array first:
Converting array of objects to the simple array with map:
var hasDupsObjects = function(array) {
return array.map(function(value) {
return value.suit + value.rank
}).some(function(value, index, array) {
return array.indexOf(value) !== array.lastIndexOf(value);
})
}
Tests:
var cardHand = [
{ "suit":"spades", "rank":"ten" },
{ "suit":"diamonds", "rank":"ace" },
{ "suit":"hearts", "rank":"ten" },
{ "suit":"clubs", "rank":"two" },
{ "suit":"spades", "rank":"three" },
]
hasDupsObjects(cardHand);
// => false
var cardHand2 = [
{ "suit":"spades", "rank":"ten" },
{ "suit":"diamonds", "rank":"ace" },
{ "suit":"hearts", "rank":"ten" },
{ "suit":"clubs", "rank":"two" },
{ "suit":"spades", "rank":"ten" },
]
hasDupsObjects(cardHand2);
// => true
if you are looking for a boolean, the quickest way would be
var values = [
{ name: 'someName1' },
{ name: 'someName2' },
{ name: 'someName1' },
{ name: 'someName1' }
]
// solution
var hasDuplicate = false;
values.map(v => v.name).sort().sort((a, b) => {
if (a === b) hasDuplicate = true
})
console.log('hasDuplicate', hasDuplicate)
const values = [
{ name: 'someName1' },
{ name: 'someName2' },
{ name: 'someName4' },
{ name: 'someName4' }
];
const foundDuplicateName = values.find((nnn, index) =>{
return values.find((x, ind)=> x.name === nnn.name && index !== ind )
})
console.log(foundDuplicateName)
Found the first one duplicate name
const values = [
{ name: 'someName1' },
{ name: 'someName2' },
{ name: 'someName4' },
{ name: 'someName4' }
];
const foundDuplicateName = values.find((nnn, index) =>{
return values.find((x, ind)=> x.name === nnn.name && index !== ind )
})
You just need one line of code.
var values = [
{ name: 'someName1' },
{ name: 'someName2' },
{ name: 'someName4' },
{ name: 'someName2' }
];
let hasDuplicates = values.map(v => v.name).length > new Set(values.map(v => v.name)).size ? true : false;
Try an simple loop:
var repeat = [], tmp, i = 0;
while(i < values.length){
repeat.indexOf(tmp = values[i++].name) > -1 ? values.pop(i--) : repeat.push(tmp)
}
Demo
With Underscore.js A few ways with Underscore can be done. Here is one of them. Checking if the array is already unique.
function isNameUnique(values){
return _.uniq(values, function(v){ return v.name }).length == values.length
}
With vanilla JavaScript
By checking if there is no recurring names in the array.
function isNameUnique(values){
var names = values.map(function(v){ return v.name });
return !names.some(function(v){
return names.filter(function(w){ return w==v }).length>1
});
}
//checking duplicate elements in an array
var arr=[1,3,4,6,8,9,1,3,4,7];
var hp=new Map();
console.log(arr.sort());
var freq=0;
for(var i=1;i<arr.length;i++){
// console.log(arr[i-1]+" "+arr[i]);
if(arr[i]==arr[i-1]){
freq++;
}
else{
hp.set(arr[i-1],freq+1);
freq=0;
}
}
console.log(hp);
You can use map to return just the name, and then use this forEach trick to check if it exists at least twice:
var areAnyDuplicates = false;
values.map(function(obj) {
return obj.name;
}).forEach(function (element, index, arr) {
if (arr.indexOf(element) !== index) {
areAnyDuplicates = true;
}
});
Fiddle
Adding updated es6 function to check for unique and duplicate values in array. This function is modular and can be reused throughout the code base. Thanks to all the post above.
/* checks for unique keynames in array */
const checkForUnique = (arrToCheck, keyName) => {
/* make set to remove duplicates and compare to */
const uniqueValues = [...new Set(arrToCheck.map(v => v[keyName]))];
if(arrToCheck.length !== uniqueValues.length){
console.log('NOT UNIQUE')
return false
}
return true
}
let arr = [{name:'joshua'},{name:'tony'},{name:'joshua'}]
/* call function with arr and key to check for */
let isUnique = checkForUnique(arr,'name')
checkDuplicate(arr, item) {
const uniqueValues = new Set(arr.map((v) => v[item]));
return uniqueValues.size < arr.length;
},
console.log(this.checkDuplicate(this.dutyExemptionBase, 'CI_ExemptionType')); // true || false
It is quite interesting to work with arrays
You can use new Set() method to find duplicate values!
let's assume you have an array of objects like this...
let myArray = [
{ id: 0, name: "Jhon" },
{ id: 1, name: "sara" },
{ id: 2, name: "pop" },
{ id: 3, name: "sara" }
]
const findUnique = new Set(myArray.map(x => {
return x.name
}))
if(findUnique.size < myArray.length){
console.log("duplicates found!")
}else{
console.log("Done!")
}
const duplicateValues = [{ name: "abc" }, { name: "bcv" }, { name: "abc" }];
const isContainDuplicate = (params) => {
const removedDuplicate = new Set(params.map((el) => el.name));
return params.length !== removedDuplicate.size;
};
const isDuplicate = isContainDuplicate(duplicateValues);
console.log("isDuplicate");

Filter Array based on another array

I have a list with that contains a list of objects. Each object has 4 properties on it. There is a checkbox list with the unique values of two of the properties, this helps build my filter array.
the Filter might end up looking like this:
[
{
prop: 'username',
val: ['max', 'sam']
},
{
prop: 'color',
val: ['blue', 'green']
}
]
The list of objects would look something like this:
[
{
username: 'sam',
color: 'blue'
},
{
username: 'jimmy',
color: 'blue'
},
{
username: 'sam',
color: 'black'
},
{
username: 'max',
color: 'green'
},
{
username: 'max',
color: 'blue'
}
]
The Desired Result
[
{
username: 'sam',
color: 'blue'
},
{
username: 'max',
color: 'green'
},
{
username: 'max',
color: 'blue'
}
]
I feel like I'm going down a never ending forEach rabbit hole. I'm guessing I need some sort of recursion. Currently here is what I have:
var temporary = scope.transactions;
function getFilteredTransactions() {
var filter = deviceFilterService.get();
if (filter.length > 0) {
var temp2 = [];
angular.forEach(filter, function (fil) {
//object
angular.forEach(fil.val, function (filterValue) {
//list on each object
angular.forEach(temporary, function (transaction) {
if (transaction[fil.prop] === filterValue) {
if (temp2.indexOf(transaction) === -1) {
temp2.push(transaction);
}
}
});
temporary = temp2;
});
});
$log.debug(temporary);
scope.transactions = temporary;
} else {
initialize();
}
}
This is starting to work, the second time it goes through the property for color it ends up just wanting to add the exact same transaction to the temp2 array. There has to be a better way to set this up, possibly through recursion.
If you convert the format of the first list to a dictionary, i think if should get easier.
var dict = {};
angular.forEach(source1, function(ob){
dict[ob.prop] = ob.val;
});
function getFiltered(ob){
for(var prop in ob){
if(dict[prop] && dict[prop].indexOf(ob[prop]) === -1){
return false;
}
}
return true;
};
and just call it as:
var temporary = scope.transactions.filter(getFiltered);
Demo
Basically the first part converts:
[
{
prop: 'username',
val: ['max', 'sam']
},
{
prop: 'color',
val: ['blue', 'green']
}
];
to:
{
username:['max', 'sam'],
color:['blue', 'green']
}
so that it makes the look up much easier.
You might want to change the variable names here for clarity, but this will do what you're asking for:
var values = {};
angular.forEach(startingData, function(rawData) {
angular.forEach(rawData, function(value, key) {
if (angular.isUndefined(values[key])) {
values[key] = [];
}
if (values[key].indexOf(value) === -1) {
values[key].push(value);
}
})
});
var result = [];
angular.forEach(values, function(value, key) {
result.push({prop: key, val: value})
});
You can simply iterate each key of the data the needs filtering, find the appropriate filter per that key, and check the value against the filter values:
$scope.transactions = $scope.transactions.filter(isItemValidFilter);
function isItemValidFilter(item) {
var filters = deviceFilterService.get();
//For each property in the data, get the correct filter from the list of filters
var totalConditions = Object.keys(item).length;
var correctConditions = 0;
for (var filterKey in item) {
var correctFilters = filters.filter(function(dataFilter) {
return dataFilter.prop == filterKey
});
if (correctFilters.length) {
//Ill assume only 1 filter, so just use the 0 index
var correctFilter = correctFilters[0];
var conditions = correctFilter.val;
if (conditions && conditions.length) {
//check the values!
if (conditions.indexOf(item[filterKey]) > -1) {
correctConditions++;
}
}
}
}
return correctConditions === totalConditions;
}
Demo: http://jsfiddle.net/Lz32hka5/1/
Try:
var temp2 = [], matched;
angular.forEach(temporary, function(item){
matched = true;
angular.forEach(Object.keys(item), function(key){
angular.forEach(filter, function(filter){
filter.prop == key && filter.val.indexOf(item[key]) == -1 && (matched = false);
});
});
matched && temp2.push(item);
});
console.log(temp2)
temporary is the list of objects, filter: your filters
Demo: http://jsfiddle.net/wZVanG/7wnae850/

Categories