Related
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");
var a = [ { id:1}, {id:2} ];
var b = {id:1};
var res = a.indexOf(b._id) == -1;
console.log(res);
I want to check if b._id is in a[].
Note: a[] is an array of objects
Try this..
var a = [{ id:1}, {id:2}];
var b={id:1};
var arrayWithIds = a.map(function(x){
return x.id
}); // get new array contains all ids
var present = arrayWithIds.indexOf(b.id) != -1 // find the b.id array
console.log(present);
Here is the reference for Map and indexOf
This should work :
var a = [ { id:1} ,{id:2} ];
var b={id:1}
console.log(a.findIndex(function(obj){return obj.id=b.id}))
indexOf works when you are dealing with indexed arrays not with array of objects.
Please use the following code:
var a = [ { id:1}, {id:2} ];
var b={id:1}
function findMatch(element) {
return element.id === b.id;
}
console.log(a.findIndex(findMatch));
A better way is using .find function.
let a = [{
id: 1
}, {
id: 2
}],
b = {
id: 1
},
obj = a.find(function(itm) {
return itm.id == b.id;
});
console.log(obj)
And also using .findIndex function to get just index of item in array.
let a = [{
id: 1
}, {
id: 2
}],
b = {
id: 1
},
objIndex = a.findIndex(function(itm) {
return itm.id == b.id;
});
console.log(objIndex)
And for getting all objects with that condition use .filter function.
let a = [{
id: 1
}, {
id: 2
}],
b = {
id: 1
},
objArr = a.filter(function(itm) {
return itm.id == b.id;
});
console.log(objArr)
Array.map() function compare id and its value and return a Boolean value if map as commented by #Slava Utesinov
var a = [{id: 1}, {id: 2}];
var b = {id: 1};
if(a.map(x => x.id).indexOf(b.id) != -1){
console.log("Exists");
}else{
console.log("Not exists");
}
try this
var a = [ { id:1} ,{id:2} ];
var b={id:1}
console.log(a.find(x=>x.id==b.id))// return matched record
var a = [ { id:1} ,{id:2} ];
var b={id:3}
console.log(a.find(x=>x.id==b.id)) //return undefined
Use Array.map() function of JavaScript to check it. It will compare id and its value as well.
Below is working code:
var a = [{
id: 1
}, {
id: 2
}];
var b = {
id: 1
};
if (a.map(x => x.id).indexOf(b.id) != -1) {
console.log("Available");
} else {
console.log("Not available");
}
You can use Filter of AngularJS
var a = [{id:1}, {id:2}];
var b = {id:1};
var found = false;
var filterResult = $filter('filter')(a, {id: b.id}, true);
if (filterResult.length > 0) {
found = true;
}
How do I set deep properties in a JavaScript object using a dot-syntax string to specify which property I want to change?
For simple objects, I could just use data['property_name'] = 'foo', but I don't necessarily know how deeply nested the data is going to be.
Below is some example code with how I'd like to be able to format the data in the end. For all I know there's a nice way that JS already allows you to do this, but I haven't been able to find it yet.
Plunker here.
var items = [
{
lookup_string: "User.UserProfile.name",
value: "John Smith"
},
{
lookup_string: "User.email",
value: "johnsmith#example.com"
},
]
var data = {};
items.forEach(function(item){
// Inside this loop, set the appropriate keys under data. Is there a non-convoluted way to do this?
});
console.log("items", items);
console.log("Results", data)
// In the end, data should look like this:
var desiredData = {
User: {
UserProfile: {
name: 'John Smith'
},
email: 'johnsmith#example.com'
}
}
You could split the lookup_string and reduce an object with a default object. Later assign the value.
function setValue(object, path, value) {
var keys = path.split('.'),
last = keys.pop();
keys.reduce(function (o, k) {
return o[k] = o[k] || {};
}, object)[last] = value;
}
var items = [{ lookup_string: "User.UserProfile.name", value: "John Smith" }, { lookup_string: "User.email", value: "johnsmith#example.com" }],
object = {};
items.forEach(function(o) {
setValue(object, o.lookup_string, o.value);
});
console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }
you will have to loop over all the keys from lookup_string.split('.') and assign values, something like this:
var items = [
{
lookup_string: "User.UserProfile.name",
value: "John Smith"
},
{
lookup_string: "User.email",
value: "johnsmith#example.com"
},
];
var data = {};
items.forEach(function(item){
var lookup = item.lookup_string.split('.');
var lastKey;
lookup.map(function(key){
data[key] = {};
lastKey = key;
});
data[lastKey] = item.value;
});
console.log("items", items);
console.log("Results", data)
// In the end, data should look like this:
var desiredData = {
User: {
UserProfile: {
name: 'John Smith'
},
email: 'johnsmith#example.com'
}
};
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");
I have an object being returned by a legacy server and I want to change the structure on the client-side via JavaScript, jQuery, or even Underscore.js.
Below is what my original object looks like:
[
{
"Id":{
"LValue":1,
"Value":1
},
"Date":{
"LValue":"2013-10-17T00:00:00",
"Value":"2013-10-24T00:00:00"
},
"User":{
"LValue":508,
"Value":507
},
"Comments":{
"LValue":"This a test load",
"Value":"This a test"
},
"Name":"John Doe",
"IsDeleted":false
}
]
On the client-side though, I would like to flatten it to get the "Values" and stuff the "LValues" into a separate property so I don't loose them if I need it later:
[
{
"Id":1,
"Date":"2013-10-24T00:00:00",
"User":507,
"Comments":"This a test",
"Name":"John Doe",
"IsDeleted":false,
"LValues": {
"Id":1,
"Date":"2013-10-17T00:00:00",
"User":508,
"Comments":"This a test load"
}
}
]
this would make working with the object so much easier and any help would be deeply appreciated!
var oList = [
{
"Id":{
"LValue":1,
"Value":1
},
"Date":{
"LValue":"2013-10-17T00:00:00",
"Value":"2013-10-24T00:00:00"
},
"User":{
"LValue":508,
"Value":507
},
"Comments":{
"LValue":"This a test load",
"Value":"This a test"
},
"Name":"John Doe",
"IsDeleted":false
}
];
var newFormat = _(oList).map(function(o) {
var flattened = { LValues: {} };
_(o).each(function(val, propName) {
flattened[propName] = val.Value ? val.Value : val;
if(val.LValue) {
flattened.LValues[propName] = val.LValue;
}
});
return flattened;
}
You could use a basic Javascript map for this. Assuming hard-coded properties:
var flattenedItems = items.map(function(x) {
return {
Id: x.Id.Value,
Date: x.Date.Value,
User: x.User.Value,
Comments: x.Comments.Value,
Name: x.Name,
IsDeleted: x.IsDeleted,
LValues: {
Id: x.Id.LValue,
Date: x.Date.LValue,
User: x.User.LValue,
Comments: x.Comments.LValue,
}
};
});
(Fiddle)
If the properties are variable, then you could iterate through them inside the map iterator:
var flattenedItems = items.map(function(x) {
var flattened = { LValues: {} };
for (var prop in x) {
flattened[prop] = x[prop].Value;
flattened.LValues[prop] = x[prop].LValue;
};
return flattened;
});
(Fiddle)
You could use
var items = [
{
"Id":{
"LValue":1,
"Value":1
},
// ...
}
];
items = items[0];
var obj = {LValues: {}};
for(var i in items) {
if(typeof items[i] === 'object') {
obj[i] = items[i].Value;
obj.LValues[i] = items[i].LValue;
} else {
obj[i] = items[i];
}
}
I believe that the output is actually write a simple function
function flatten(obj){
var r = {};
if(obj){
console.log(obj);
r.Id = obj.Id.Value;
r.Date = obj.Date.Value;
r.User = obj.User.Value;
r.Comments = obj.Comments.Value;
r.Name = obj.Name.Value;
r.IsDeleted = obj.IsDeleted;
r.LValues = {};
r.LValues.Id = obj.Id.LValue;
r.LValues.Date = obj.Date.LValue;
r.LValues.User = obj.User.LValue;
r.LValues.Comments = obj.Comments.LValue;
}
return r;
}