I would like to find index in array. Positions in array are objects, and I want to filter on their properties. I know which keys I want to filter and their values. Problem is to get index of array which meets the criteria.
For now I made code to filter data and gives me back object data, but not index of array.
var data = [
{
"text":"one","siteid":"1","chid":"default","userid":"8","time":1374156747
},
{
"text":"two","siteid":"1","chid":"default","userid":"7","time":1374156735
}
];
var filterparams = {userid:'7', chid: 'default'};
function getIndexOfArray(thelist, props){
var pnames = _.keys(props)
return _.find(thelist, function(obj){
return _.all(pnames, function(pname){return obj[pname] == props[pname]})
})};
var check = getIndexOfArray(data, filterparams ); // Want to get '2', not key => val
Using Lo-Dash in place of underscore you can do it pretty easily with _.findIndex().
var index = _.findIndex(array, { userid: '7', chid: 'default' })
here is thefiddle hope it helps you
for(var intIndex=0;intIndex < data.length; intIndex++){
eachobj = data[intIndex];
var flag = true;
for (var k in filterparams) {
if (eachobj.hasOwnProperty(k)) {
if(eachobj[k].toString() != filterparams[k].toString()){
flag = false;
}
}
}
if(flag){
alert(intIndex);
}
}
I'm not sure, but I think that this is what you need:
var data = [{
"text":"one","siteid":"1","chid":"default","userid":"8","time":1374156747
}, {
"text":"two","siteid":"1","chid":"default","userid":"7","time":1374156735
}];
var filterparams = {userid:'7', chid: 'default'};
var index = data.indexOf( _.findWhere( data, filterparams ) );
I don't think you need underscore for that just regular ole js - hope this is what you are looking for
var data = [
{
"text":"one","siteid":"1","chid":"default","userid":"8","time":1374156747
},
{
"text":"two","siteid":"1","chid":"default","userid":"7","time":1374156735
}
];
var userid = "userid"
var filterparams = {userid:'7', chid: 'default'};
var index;
for (i=0; i < data.length; i++) {
for (prop in data[i]) {
if ((prop === userid) && (data[i]['userid'] === filterparams.userid)) {
index = i
}
}
}
alert(index);
Related
I have array object(x) that stores json (key,value) objects. I need to make sure that x only takes json object with unique key. Below, example 'id' is the key, so i don't want to store other json objects with 'item1' key.
x = [{"id":"item1","val":"Items"},{"id":"item1","val":"Items"},{"id":"item1","val":"Items"}]
var clickId = // could be "item1", "item2"....
var found = $.inArray(clickId, x); //
if(found >=0)
{
x.splice(found,1);
}
else{
x.push(new Item(clickId, obj)); //push json object
}
would this accomplish what you're looking for? https://jsfiddle.net/gukv9arj/3/
x = [
{"id":"item1","val":"Items"},
{"id":"item1","val":"Items"},
{"id":"item2","val":"Items"}
];
var clickId = [];
var list = JSON.parse(x);
$.each(list, function(index, value){
if(clickId.indexOf(value.id) === -1){
clickId.push(value.id);
}
});
You can't use inArray() because you are searching for an object.
I'd recommend rewriting a custom find using Array.some() as follows.
var x = [{"id":"item1","val":"Items"},{"id":"item1","val":"Items"},{"id":"item1","val":"Items"}]
var clickId = "item1";
var found = x.some(function(value) {
return value.id === clickId;
});
alert(found);
Almost 6 years later i ended up in this question, but i needed to fill a bit more complex array, with objects. So i needed to add something like this.
var values = [
{value: "value1", selected: false},
{value: "value2", selected: false}
//there cannot be another object with value = "value1" within the collection.
]
So I was looking for the value data not to be repeated (in an object's array), rather than just the value in a string's array, as required in this question. This is not the first time i think in doing something like this in some JS code.
So i did the following:
let valueIndex = {};
let values = []
//I had the source data in some other and more complex array.
for (const index in assetsArray)
{
const element = assetsArray[index];
if (!valueIndex[element.value])
{
valueIndex[element.value] = true;
values.push({
value: element.value,
selected: false
});
}
}
I just use another object as an index, so the properties in an object will never be repated. This code is quite easy to read and surely is compatible with any browser. Maybe someone comes with something better. You are welcome to share!
Hopes this helps someone else.
JS objects are great tools to use for tracking unique items. If you start with an empty object, you can incrementally add keys/values. If the object already has a key for a given item, you can set it to some known value that is use used to indicate a non-unique item.
You could then loop over the object and push the unique items to an array.
var itemsObj = {};
var itemsList = [];
x = [{"id":"item1","val":"foo"},
{"id":"item2","val":"bar"},
{"id":"item1","val":"baz"},
{"id":"item1","val":"bez"}];
for (var i = 0; i < x.length; i++) {
var item = x[i];
if (itemsObj[item.id]) {
itemsObj[item.id] = "dupe";
}
else {
itemsObj[item.id] = item;
}
}
for (var myKey in itemsObj) {
if (itemsObj[myKey] !== "dupe") {
itemsList.push(itemsObj[myKey]);
}
}
console.log(itemsList);
See a working example here: https://jsbin.com/qucuso
If you want a list of items that contain only the first instance of an id, you can do this:
var itemsObj = {};
var itemsList = [];
x = [{"id":"item1","val":"foo"},
{"id":"item2","val":"bar"},
{"id":"item1","val":"baz"},
{"id":"item1","val":"bez"}];
for (var i = 0; i < x.length; i++) {
var item = x[i];
if (!itemsObj[item.id]) {
itemsObj[item.id] = item;
itemsList.push(item);
}
}
console.log(itemsList);
This is late but I did something like the following:
let MyArray = [];
MyArray._PushAndRejectDuplicate = function(el) {
if (this.indexOf(el) == -1) this.push(el)
else return;
}
MyArray._PushAndRejectDuplicate(1); // [1]
MyArray._PushAndRejectDuplicate(2); // [1,2]
MyArray._PushAndRejectDuplicate(1); // [1,2]
This is how I would do it in pure javascript.
var x = [{"id":"item1","val":"Items"},{"id":"item1","val":"Items"},{"id":"item1","val":"Items"}];
function unique(arr, comparator) {
var uniqueArr = [];
for (var i in arr) {
var found = false;
for (var j in uniqueArr) {
if (comparator instanceof Function) {
if (comparator.call(null, arr[i], uniqueArr[j])) {
found = true;
break;
}
} else {
if (arr[i] == uniqueArr[j]) {
found = true;
break;
}
}
}
if (!found) {
uniqueArr.push(arr[i]);
}
}
return uniqueArr;
};
u = unique(x, function(a,b){ return a.id == b.id; });
console.log(u);
y = [ 1,1,2,3,4,5,5,6,1];
console.log(unique(y));
Create a very readable solution with lodash.
x = _.unionBy(x, [new Item(clickId, obj)], 'id');
let x = [{id:item1,data:value},{id:item2,data:value},{id:item3,data:value}]
let newEle = {id:newItem,data:value}
let prev = x.filter(ele=>{if(ele.id!=new.id)return ele);
newArr = [...prev,newEle]
I have an array:
["car1-coupe", "car2-convertible", "car2-hatchback", "car2-estate", "car3-hatchback", "car3-estate"]
The array can have different sets of cars, and I want to turn it into something like this:
[{
car1: ["car1-coupe"]
},{
car2: ["car2-convertible", "car2-hatchback", "car2-estate"]
},{
car3: ["car3-hatchback", "car3-estate"]
}]
How can I do this in JavaScript or Underscore?
So, assuming an array like this:
var a = ["car1-coupe", "car2-convertible", "car2-hatchback", "car2-estate", "car3-hatchback", "car3-estate"];
You can do this:
var b = a.reduce(function(prev, curr){
var car = curr.split('-')[0]; // "get" the current car
prev[car] = prev[car] || []; // Initialize the array for the current car, if necessary.
prev[car].push(curr); // Add the current item to the array.
return prev;
}, {});
This will return the following object:
{
car1: ["car1-coupe"],
car2: ["car2-convertible", "car2-hatchback", "car2-estate"],
car3: ["car3-hatchback", "car3-estate"]
}
var array = ["car1-coupe", "car2-convertible", "car2-hatchback", "car2-estate", "car3-hatchback", "car3-estate"];
var result = {};
for (var i = 0; i < array.length; i++) {
var key = array[i].split('-')[0]; // The car we're interested in
if (result[key]) { // Check if this car has already been initialized
result[key].push(array[i]); //add this model to the list
} else {
result[key] = [array[i]]; // initialize the array with the first value
}
}
console.log(result);
/*will return :
{
car1: ["car1-coupe"],
car2: ["car2-convertible", "car2-hatchback", "car2-estate"],
car3: ["car3-hatchback", "car3-estate"]
}
*/
var myObj = {}, myArr = [];
for( var i = 0; i < arr.length; i+=1) {
var key = arr[i].split("-")[0];
myObj = {};
myObj[key] = [];
for( var j = i; j < arr.length; j+=1 ) {
if( key === arr[j].split("-")[0])
myObj[key].push(arr[j]);
}
myArr.push(myObj);
}
I think this can be done simply with this way. One loop to get the key and another inner loop to get all values of this key.
Given data such as :
var people = [
{ 'myKey': 'John Kenedy', 'status': 1 },
{ 'myKey': 'Steeven Red', 'status': 0 },
{ 'myKey': 'Mary_Kenedy', 'status': 3 },
{ 'myKey': 'Carl Orange', 'status': 0 },
{ 'myKey': 'Lady Purple', 'status': 0 },
... // thousands more
];
How to efficiently get the list of all objects which contains in myKey the string Kenedy ?
http://jsfiddle.net/yb3rdhm8/
Note: I currently use str.search() :
The search("str") returns the position of the match. Returns -1 if no match is found.
to do as follow :
var map_partial_matches = function(object, str){
var list_of_people_with_kenedy = [] ;
for (var j in object) {
if (object[j]["myKey"].search(str) != -1) {
object[j].presidentName = "yes"; // do something to object[j]
list_of_people_with_kenedy.push({ "people": object[j]["myKey"] }); // add object key to new list
}
} return list_of_people_with_kenedy;
}
map_partial_matches(people, "Kenedy");
I could do the same using str.match() :
str.match() returns the matches, as an Array object. Returns null if no match is found.
It works anyway, but I have no idea if it's efficient or completely dump.
You can use filter():
var filtered = people.filter(function (item) {
if (item.myKey.indexOf("Kenedy") != -1)
return item;
});
You can also checkout Sugar.js
In order to search your unsorted object you need to get through all of it's properties - So I'd say a simple loop with an indexOf will be pretty much the best you can go:
var foundItems = [];
for(var i = 0; i < people.length ;i++)
{
if(people[i].myKey.indexOf('Kenedy') > -1)
foundItems.push(people[i]]);
}
Maybe you can tweak it up a little, but it's pretty much the best you can get.
You can write a basic function that uses filter to return an array of matches based on a key and value:
function find(arr, key, val) {
return arr.filter(function (el) {
return el[key].indexOf(val) > -1;
});
}
var result = find(people, 'myKey', 'Kenedy');
Alternatively use a normal for...loop:
function find(arr, key, val) {
var out = [];
for (var i = 0, l = arr.length; i < l; i++) {
if (arr[i][key].indexOf(val) > -1) {
out.push(arr[i]);
}
}
return out;
}
DEMO
Does the Object Contain a Given Key?
function hKey(obj, key) {
arr = [];
// newarr =[];
for(el in obj){
arr.push(el)
} //return arr;
for(i=0; i<arr.length; i++){
name = arr[i]
} if(name == key) {
return true;
}else {
return false;
}
}
console.log(hKey({ a: 44, b: 45, c: 46 }, "c"))
For example, I have:
var Data = [
{ id_list: 1, name: 'Nick', token: '312312' },
{ id_list: 2, name: 'John', token: '123123' },
]
Then, I want to sort/reverse this object by name, for example. And then I want to get something like this:
var Data = [
{ id_list: 2, name: 'John', token: '123123' },
{ id_list: 1, name: 'Nick', token: '312312' },
]
And now I want to know the index of the object with property name='John' to get the value of the property token.
How do I solve the problem?
Since the sort part is already answered. I'm just going to propose another elegant way to get the indexOf of a property in your array
Your example is:
var Data = [
{id_list:1, name:'Nick', token:'312312'},
{id_list:2, name:'John', token:'123123'}
]
You can do:
var index = Data.map(function(e) { return e.name; }).indexOf('Nick');
var Data = [{
id_list: 1,
name: 'Nick',
token: '312312'
},
{
id_list: 2,
name: 'John',
token: '123123'
}
]
var index = Data.map(function(e) {
return e.name;
}).indexOf('Nick');
console.log(index)
Array.prototype.map is not available on Internet Explorer 7 or Internet Explorer 8. ES5 Compatibility
And here it is with ES6 and arrow syntax, which is even simpler:
const index = Data.map(e => e.name).indexOf('Nick');
If you're fine with using ES6, arrays now have the findIndex function. Which means you can do something like this:
const index = Data.findIndex(item => item.name === 'John');
As the other answers suggest, looping through the array is probably the best way. But I would put it in its own function, and make it a little more abstract:
function findWithAttr(array, attr, value) {
for(var i = 0; i < array.length; i += 1) {
if(array[i][attr] === value) {
return i;
}
}
return -1;
}
var Data = [
{id_list: 2, name: 'John', token: '123123'},
{id_list: 1, name: 'Nick', token: '312312'}
];
With this, not only can you find which one contains 'John', but you can find which contains the token '312312':
findWithAttr(Data, 'name', 'John'); // returns 0
findWithAttr(Data, 'token', '312312'); // returns 1
findWithAttr(Data, 'id_list', '10'); // returns -1
The function returns -1 when not found, so it follows the same construct as Array.prototype.indexOf().
If you're having issues with Internet Explorer, you could use the map() function which is supported from 9.0 onward:
var index = Data.map(item => item.name).indexOf("Nick");
var index = Data.findIndex(item => item.name == "John")
Which is a simplified version of:
var index = Data.findIndex(function(item){ return item.name == "John"})
From mozilla.org:
The findIndex() method returns the index of the first element in the array that satisfies the provided testing function. Otherwise -1 is returned.
Only way known to me is to loop through all array:
var index = -1;
for(var i=0; i<Data.length; i++)
if(Data[i].name === "John") {
index = i;
break;
}
Or case insensitive:
var index = -1;
for(var i=0; i<Data.length; i++)
if(Data[i].name.toLowerCase() === "john") {
index = i;
break;
}
On result variable index contain index of object or -1 if not found.
A prototypical way
(function(){
if (!Array.prototype.indexOfPropertyValue){
Array.prototype.indexOfPropertyValue = function(prop, value){
for (var index = 0; index < this.length; index++){
if (this[index][prop]){
if (this[index][prop] == value){
return index;
}
}
}
return -1;
}
}
})();
// Usage:
var Data = [
{id_list:1, name:'Nick', token:'312312'}, {id_list:2, name:'John', token:'123123'}];
Data.indexOfPropertyValue('name', 'John'); // Returns 1 (index of array);
Data.indexOfPropertyValue('name', 'Invalid name') // Returns -1 (no result);
var indexOfArray = Data.indexOfPropertyValue('name', 'John');
Data[indexOfArray] // Returns the desired object.
you can use filter method
const filteredData = data.filter(e => e.name !== 'john');
Just go through your array and find the position:
var i = 0;
for(var item in Data) {
if(Data[item].name == 'John')
break;
i++;
}
alert(i);
let indexOf = -1;
let theProperty = "value"
let searchFor = "something";
theArray.every(function (element, index) {
if (element[theProperty] === searchFor) {
indexOf = index;
return false;
}
return true;
});
collection.findIndex(item => item.value === 'smth') !== -1
You can use Array.sort using a custom function as a parameter to define your sorting mechanism.
In your example, it would give:
var Data = [
{id_list:1, name:'Nick',token:'312312'},{id_list:2,name:'John',token:'123123'}
]
Data.sort(function(a, b){
return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
});
alert("First name is : " + Data[0].name); // alerts 'John'
alert("Second name is : " + Data[1].name); // alerts 'Nick'
The sort function must return either -1 if a should come before b, 1 if a should come after b and 0 if both are equal. It's up to you to define the right logic in your sorting function to sort the array.
Missed the last part of your question where you want to know the index. You would have to loop through the array to find that as others have said.
This might be useful:
function showProps(obj, objName) {
var result = "";
for (var i in obj)
result += objName + "." + i + " = " + obj[i] + "\n";
return result;
}
I copied this from Working with objects.
Use a small workaround:
Create a new array with names as indexes. After that all searches will use indexes. So, only one loop. After that you don't need to loop through all elements!
var Data = [
{id_list:1, name:'Nick',token:'312312'},{id_list:2,name:'John',token:'123123'}
]
var searchArr = []
Data.forEach(function(one){
searchArr[one.name]=one;
})
console.log(searchArr['Nick'])
http://jsbin.com/xibala/1/edit
Live example.
I extended Chris Pickett's answer, because in my case I needed to search deeper than one attribute level:
function findWithAttr(array, attr, value) {
if (attr.indexOf('.') >= 0) {
var split = attr.split('.');
var attr1 = split[0];
var attr2 = split[1];
for(var i = 0; i < array.length; i += 1) {
if(array[i][attr1][attr2] === value) {
return i;
}
}
} else {
for(var i = 0; i < array.length; i += 1) {
if(array[i][attr] === value) {
return i;
}
}
};
};
You can pass 'attr1.attr2' into the function.
Use this:
Data.indexOf(_.find(Data, function(element) {
return element.name === 'John';
}));
It is assuming you are using Lodash or Underscore.js.
var fields = {
teste:
{
Acess:
{
Edit: true,
View: false
}
},
teste1:
{
Acess:
{
Edit: false,
View: false
}
}
};
console.log(find(fields,'teste'));
function find(fields,field) {
for(key in fields) {
if(key == field) {
return true;
}
}
return false;
}
If you have one Object with multiple objects inside, if you want know if some object are include on Master object, just use find(MasterObject, 'Object to Search'). This function will return the response if it exists or not (TRUE or FALSE). I hope to help with this - can see the example on JSFiddle.
If you want to get the value of the property token then you can also try this:
let data=[
{ id_list: 1, name: 'Nick', token: '312312' },
{ id_list: 2, name: 'John', token: '123123' },
]
let resultingToken = data[_.findKey(data,['name','John'])].token
where _.findKey is a Lodash function.
You can use findIndex in Lodash library.
Example:
var users = [
{ 'user': 'barney', 'active': false },
{ 'user': 'fred', 'active': false },
{ 'user': 'pebbles', 'active': true }
];
_.findIndex(users, function(o) { return o.user == 'barney'; });
// => 0
// The `_.matches` iteratee shorthand.
_.findIndex(users, { 'user': 'fred', 'active': false });
// => 1
// The `_.matchesProperty` iteratee shorthand.
_.findIndex(users, ['active', false]);
// => 0
// The `_.property` iteratee shorthand.
_.findIndex(users, 'active');
// => 2
Alternatively to German Attanasio Ruiz's answer, you can eliminate the second loop by using Array.reduce() instead of Array.map();
var Data = [
{ name: 'hypno7oad' }
]
var indexOfTarget = Data.reduce(function (indexOfTarget, element, currentIndex) {
return (element.name === 'hypno7oad') ? currentIndex : indexOfTarget;
}, -1);
Maybe the Object.keys, Object.entries, and Object.values methods might help.
Using Underscore.js:
var index = _.indexOf(_.pluck(item , 'name'), 'Nick');
I have the following array
var countries = {};
countries.results = [
{id:'AF',name:'Afghanistan'},
{id:'AL',name:'Albania'},
{id:'DZ',name:'Algeria'}
];
How can I remove an item from this array using its name or id ?
Thank you
Created a handy function for this..
function findAndRemove(array, property, value) {
array.forEach(function(result, index) {
if(result[property] === value) {
//Remove from array
array.splice(index, 1);
}
});
}
//Checks countries.result for an object with a property of 'id' whose value is 'AF'
//Then removes it ;p
findAndRemove(countries.results, 'id', 'AF');
Array.prototype.removeValue = function(name, value){
var array = $.map(this, function(v,i){
return v[name] === value ? null : v;
});
this.length = 0; //clear original array
this.push.apply(this, array); //push all elements except the one we want to delete
}
countries.results.removeValue('name', 'Albania');
Try this:
var COUNTRY_ID = 'AL';
countries.results =
countries.results.filter(function(el){ return el.id != COUNTRY_ID; });
Try this.(IE8+)
//Define function
function removeJsonAttrs(json,attrs){
return JSON.parse(JSON.stringify(json,function(k,v){
return attrs.indexOf(k)!==-1 ? undefined: v;
}));}
//use object
var countries = {};
countries.results = [
{id:'AF',name:'Afghanistan'},
{id:'AL',name:'Albania'},
{id:'DZ',name:'Algeria'}
];
countries = removeJsonAttrs(countries,["name"]);
//use array
var arr = [
{id:'AF',name:'Afghanistan'},
{id:'AL',name:'Albania'},
{id:'DZ',name:'Algeria'}
];
arr = removeJsonAttrs(arr,["name"]);
You can delete by 1 or more properties:
//Delets an json object from array by given object properties.
//Exp. someJasonCollection.deleteWhereMatches({ l: 1039, v: '3' }); ->
//removes all items with property l=1039 and property v='3'.
Array.prototype.deleteWhereMatches = function (matchObj) {
var indexes = this.findIndexes(matchObj).sort(function (a, b) { return b > a; });
var deleted = 0;
for (var i = 0, count = indexes.length; i < count; i++) {
this.splice(indexes[i], 1);
deleted++;
}
return deleted;
}
you can use delete operator to delete property by it's name
delete objectExpression.property
or iterate through the object and find the value you need and delete it:
for(prop in Obj){
if(Obj.hasOwnProperty(prop)){
if(Obj[prop] === 'myValue'){
delete Obj[prop];
}
}
}
This that only requires javascript and appears a little more readable than other answers.
(I assume when you write 'value' you mean 'id')
//your code
var countries = {};
countries.results = [
{id:'AF',name:'Afghanistan'},
{id:'AL',name:'Albania'},
{id:'DZ',name:'Algeria'}
];
// solution:
//function to remove a value from the json array
function removeItem(obj, prop, val) {
var c, found=false;
for(c in obj) {
if(obj[c][prop] == val) {
found=true;
break;
}
}
if(found){
delete obj[c];
}
}
//example: call the 'remove' function to remove an item by id.
removeItem(countries.results,'id','AF');
//example2: call the 'remove' function to remove an item by name.
removeItem(countries.results,'name','Albania');
// print our result to console to check it works !
for(c in countries.results) {
console.log(countries.results[c].id);
}
it worked for me..
countries.results= $.grep(countries.results, function (e) {
if(e.id!= currentID) {
return true;
}
});
You can do it with _.pullAllBy.
var countries = {};
countries.results = [
{id:'AF',name:'Afghanistan'},
{id:'AL',name:'Albania'},
{id:'DZ',name:'Algeria'}
];
// Remove element by id
_.pullAllBy(countries.results , [{ 'id': 'AL' }], 'id');
// Remove element by name
// _.pullAllBy(countries.results , [{ 'name': 'Albania' }], 'name');
console.log(countries);
.as-console-wrapper {
max-height: 100% !important;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Maybe this is helpful, too.
for (var i = countries.length - 1; i--;) {
if (countries[i]['id'] === 'AF' || countries[i]['name'] === 'Algeria'{
countries.splice(i, 1);
}
}
The accepted answer is problematic as it attaches a function to the Array prototype. That function will show up whenever you run thru the array using a for loop:
for (var key in yourArray) {
console.log(yourArray[key]);
}
One of the values that will show up will be the function. The only acceptable way to extend base prototypes (although it is generally discouraged as it pollutes the global space) is to use the .defineProperty method:
Object.defineProperty(Object.prototype, "removeValue", {
value: function (val) {
for (var i = 0; i < this.length; i++) {
if (this[i] === val) {
this.splice(i, 1);
i--;
}
}
return this;
},
writable: true,
configurable: true,
enumerable: false
});