Related
This question already has answers here:
Getting index of an array's element based on its properties
(7 answers)
Closed 9 years ago.
My array looks something like this:
var someArray =
[
{ id: 'someID', name: 'someName', title: 'someTitle' },
{ id: 'anotherID', name: 'anotherName', title: 'anotherTitle' },
{ id: 'otherID', name: 'otherName', title: 'otherTitle' }
];
I want to get index reference of an object that who's id === 'anotherID' in reference with someArray
I know that I can use $.grep() to return an object:
var resultArray = $.grep(columns, function(e){return e.id === 'anotherID'});
resultArray will return an array of objects that match the condition of anonymous function, but it will not return an index of that object in someArray
I am looking for JavaScript/Jquery solution.
Thank you.
A simple for:
var elementIndex = false;
for ( var index = 0, length = someArray.length; index < length; index++ ) {
if ( someArray[index].id === 'anotherID' ) {
elementIndex = index;
break;
}
}
if ( elementIndex !== false ) {
console.log(elementIndex);
}
The easiest way is going to be to write your own function (unless you have access to the built-in indexOf method and it works for you:
var indexOf = function(array, predicate) {
for(var i = 0; i < array.length; i++) {
if(predicate(array[i])) {
return i;
}
}
return -1;
}
Which you could then call like:
var index = indexOf(someArray, function(e){ return e.id === 'anotherID'; });
.reduce() is not supported by IE8
One liner using reduce:
someArray.reduce(function(p,c,i){return c.id=='anotherID'?i:p},-1);
Using jQuery's $.each:
var posIndex = '';
$.each(someArray, function(i){
if(someArray[i].id === 'anotherID'){
posIndex = i;
return false; /*Stop iterating once found. Tip from Felix Kling*/
}
});
See example fiddle (upper code part).
As you see, using jQuery is alot easier than normal JS for.
This answer considers that each id is really an identifier (a.k.a. unique) or else posIndex will return the position of the last object which has anotherID.
Update
Added 'Felix Kling' tip of return false;. Now it will return the first match only. If have more than one id with same value, use below. Thanks Felix.
If you think that might have multiple equal ids, I suggest that posIndex becomes an array and then you read the array later. Example:
var posIndexArray = [];
$.each(someOtherArray, function (i) {
if (someOtherArray[i].id === 'anotherID') {
posIndexArray.push(i);
}
});
And posIndexArray will be a comma separated list of indexes you can then use $.each on it to do whatever you want with the indexes.
See example fiddle (lower code part).
You can achieve this pretty easily using either plain ol' JavaScript or jQuery if you so choose!
le vanilla
function getById(id, objects) {
for (var i = 0, length = objects.length; i < length; i++) {
if (objects[i].id === id) {
return i;
}
}
return -1;
}
jQueryyy
function getById(id, objects) {
var index = -1;
$.each(objects, function(i) {
if (this.id === id) {
index = i;
return false;
}
});
return index;
}
From that point, you could just call your little handy-dandy helper function and check that you got a good index.
var index = getById('otherId', someArray);
if (~index) {
doSomethingAwesome(someArray[index]);
}
I have an array like this:
[{prop1:"abc",prop2:"qwe"},{prop1:"bnmb",prop2:"yutu"},{prop1:"zxvz",prop2:"qwrq"},...]
How can I get the index of the object that matches a condition, without iterating over the entire array?
For instance, given prop2=="yutu", I want to get index 1.
I saw .indexOf() but think it's used for simple arrays like ["a1","a2",...]. I also checked $.grep() but this returns objects, not the index.
As of 2016, you're supposed to use Array.findIndex (an ES2015/ES6 standard) for this:
a = [
{prop1:"abc",prop2:"qwe"},
{prop1:"bnmb",prop2:"yutu"},
{prop1:"zxvz",prop2:"qwrq"}];
index = a.findIndex(x => x.prop2 ==="yutu");
console.log(index);
It's supported in Google Chrome, Firefox and Edge. For Internet Explorer, there's a polyfill on the linked page.
Performance note
Function calls are expensive, therefore with really big arrays a simple loop will perform much better than findIndex:
let test = [];
for (let i = 0; i < 1e6; i++)
test.push({prop: i});
let search = test.length - 1;
let count = 100;
console.time('findIndex/predefined function');
let fn = obj => obj.prop === search;
for (let i = 0; i < count; i++)
test.findIndex(fn);
console.timeEnd('findIndex/predefined function');
console.time('findIndex/dynamic function');
for (let i = 0; i < count; i++)
test.findIndex(obj => obj.prop === search);
console.timeEnd('findIndex/dynamic function');
console.time('loop');
for (let i = 0; i < count; i++) {
for (let index = 0; index < test.length; index++) {
if (test[index].prop === search) {
break;
}
}
}
console.timeEnd('loop');
As with most optimizations, this should be applied with care and only when actually needed.
How can I get the index of the object tha match a condition (without iterate along the array)?
You cannot, something has to iterate through the array (at least once).
If the condition changes a lot, then you'll have to loop through and look at the objects therein to see if they match the condition. However, on a system with ES5 features (or if you install a shim), that iteration can be done fairly concisely:
var index;
yourArray.some(function(entry, i) {
if (entry.prop2 == "yutu") {
index = i;
return true;
}
});
That uses the new(ish) Array#some function, which loops through the entries in the array until the function you give it returns true. The function I've given it saves the index of the matching entry, then returns true to stop the iteration.
Or of course, just use a for loop. Your various iteration options are covered in this other answer.
But if you're always going to be using the same property for this lookup, and if the property values are unique, you can loop just once and create an object to map them:
var prop2map = {};
yourArray.forEach(function(entry) {
prop2map[entry.prop2] = entry;
});
(Or, again, you could use a for loop or any of your other options.)
Then if you need to find the entry with prop2 = "yutu", you can do this:
var entry = prop2map["yutu"];
I call this "cross-indexing" the array. Naturally, if you remove or add entries (or change their prop2 values), you need to update your mapping object as well.
What TJ Crowder said, everyway will have some kind of hidden iteration, with lodash this becomes:
var index = _.findIndex(array, {prop2: 'yutu'})
var CarId = 23;
//x.VehicleId property to match in the object array
var carIndex = CarsList.map(function (x) { return x.VehicleId; }).indexOf(CarId);
And for basic array numbers you can also do this:
var numberList = [100,200,300,400,500];
var index = numberList.indexOf(200); // 1
You will get -1 if it cannot find a value in the array.
var index;
yourArray.some(function (elem, i) {
return elem.prop2 === 'yutu' ? (index = i, true) : false;
});
Iterate over all elements of array.
It returns either the index and true or false if the condition does not match.
Important is the explicit return value of true (or a value which boolean result is true). The single assignment is not sufficient, because of a possible index with 0 (Boolean(0) === false), which would not result an error but disables the break of the iteration.
Edit
An even shorter version of the above:
yourArray.some(function (elem, i) {
return elem.prop2 === 'yutu' && ~(index = i);
});
Using Array.map() and Array.indexOf(string)
const arr = [{
prop1: "abc",
prop2: "qwe"
}, {
prop1: "bnmb",
prop2: "yutu"
}, {
prop1: "zxvz",
prop2: "qwrq"
}]
const index = arr.map(i => i.prop2).indexOf("yutu");
console.log(index);
The best & fastest way to do this is:
const products = [
{ prop1: 'telephone', prop2: 996 },
{ prop1: 'computadora', prop2: 1999 },
{ prop1: 'bicicleta', prop2: 995 },
];
const index = products.findIndex(el => el.prop2 > 1000);
console.log(index); // 1
I have seen many solutions in the above.
Here I am using map function to find the index of the search text in an array object.
I am going to explain my answer with using students data.
step 1: create array object for the students(optional you can create your own array object).
var students = [{name:"Rambabu",htno:"1245"},{name:"Divya",htno:"1246"},{name:"poojitha",htno:"1247"},{name:"magitha",htno:"1248"}];
step 2: Create variable to search text
var studentNameToSearch = "Divya";
step 3: Create variable to store matched index(here we use map function to iterate).
var matchedIndex = students.map(function (obj) { return obj.name; }).indexOf(studentNameToSearch);
var students = [{name:"Rambabu",htno:"1245"},{name:"Divya",htno:"1246"},{name:"poojitha",htno:"1247"},{name:"magitha",htno:"1248"}];
var studentNameToSearch = "Divya";
var matchedIndex = students.map(function (obj) { return obj.name; }).indexOf(studentNameToSearch);
console.log(matchedIndex);
alert("Your search name index in array is:"+matchedIndex)
You can use the Array.prototype.some() in the following way (as mentioned in the other answers):
https://jsfiddle.net/h1d69exj/2/
function findIndexInData(data, property, value) {
var result = -1;
data.some(function (item, i) {
if (item[property] === value) {
result = i;
return true;
}
});
return result;
}
var data = [{prop1:"abc",prop2:"qwe"},{prop1:"bnmb",prop2:"yutu"},{prop1:"zxvz",prop2:"qwrq"}]
alert(findIndexInData(data, 'prop2', "yutu")); // shows index of 1
function findIndexByKeyValue(_array, key, value) {
for (var i = 0; i < _array.length; i++) {
if (_array[i][key] == value) {
return i;
}
}
return -1;
}
var a = [
{prop1:"abc",prop2:"qwe"},
{prop1:"bnmb",prop2:"yutu"},
{prop1:"zxvz",prop2:"qwrq"}];
var index = findIndexByKeyValue(a, 'prop2', 'yutu');
console.log(index);
Try this code
var x = [{prop1:"abc",prop2:"qwe"},{prop1:"bnmb",prop2:"yutu"},{prop1:"zxvz",prop2:"qwrq"}]
let index = x.findIndex(x => x.prop1 === 'zxvz')
Another easy way is :
function getIndex(items) {
for (const [index, item] of items.entries()) {
if (item.prop2 === 'yutu') {
return index;
}
}
}
const myIndex = getIndex(myArray);
Georg have already mentioned ES6 have Array.findIndex for this.
And some other answers are workaround for ES5 using Array.some method.
One more elegant approach can be
var index;
for(index = yourArray.length; index-- > 0 && yourArray[index].prop2 !== "yutu";);
At the same time I will like to emphasize, Array.some may be implemented with binary or other efficient searching technique. So, it might perform better over for loop in some browser.
Why do you not want to iterate exactly ? The new Array.prototype.forEach are great for this purpose!
You can use a Binary Search Tree to find via a single method call if you want. This is a neat implementation of BTree and Red black Search tree in JS - https://github.com/vadimg/js_bintrees - but I'm not sure whether you can find the index at the same time.
One step using Array.reduce() - no jQuery
var items = [{id: 331}, {id: 220}, {id: 872}];
var searchIndexForId = 220;
var index = items.reduce(function(searchIndex, item, index){
if(item.id === searchIndexForId) {
console.log('found!');
searchIndex = index;
}
return searchIndex;
}, null);
will return null if index was not found.
var list = [
{prop1:"abc",prop2:"qwe"},
{prop1:"bnmb",prop2:"yutu"},
{prop1:"zxvz",prop2:"qwrq"}
];
var findProp = p => {
var index = -1;
$.each(list, (i, o) => {
if(o.prop2 == p) {
index = i;
return false; // break
}
});
return index; // -1 == not found, else == index
}
I have the object below that is used by datatables, I want to know how to remove items by name.
Example
Lets say I want to remove sEcho, mDataProp_1 and sSearch from the object below, would the best way to loop through all items and check the name or is there a easier way.
[{"name":"sEcho","value":1},{"name":"iColumns","value":9},
{"name":"sColumns","value":""},{"name":"iDisplayStart","value":0},
{"name":"iDisplayLength","value":10},{"name":"mDataProp_0","value":0},
{"name":"mDataProp_1","value":1},{"name":"mDataProp_2","value":2},
{"name":"mDataProp_3","value":3},{"name":"mDataProp_4","value":4},
{"name":"mDataProp_5","value":5},{"name":"mDataProp_6","value":6},
{"name":"mDataProp_7","value":7},{"name":"mDataProp_8","value":8},
{"name":"sSearch","value":""},{"name":"bRegex","value":false},
{"name":"sSearch_0","value":""},{"name":"bRegex_0","value":false},
{"name":"bSearchable_0","value":false},{"name":"sSearch_1","value":""},
{"name":"bRegex_1","value":false},{"name":"bSearchable_1","value":false},
{"name":"sSearch_2","value":""},{"name":"bRegex_2","value":false}]
Examples would be great.
Thanks
Here is a little jsfiddle that do just that http://jsfiddle.net/wHkTS/
The idea is to iterate over the area and compare the name you want to remove with the currently iterate object name and basically build a new array to assign back that doesn't contain the object you want to remove.
var data = [
{"name":"sEcho","value":1},{"name":"iColumns","value":9},
{"name":"sColumns","value":""},{"name":"iDisplayStart","value":0},
{"name":"iDisplayLength","value":10},{"name":"mDataProp_0","value":0},
{"name":"mDataProp_1","value":1},{"name":"mDataProp_2","value":2},
{"name":"mDataProp_3","value":3},{"name":"mDataProp_4","value":4},
{"name":"mDataProp_5","value":5},{"name":"mDataProp_6","value":6},
{"name":"mDataProp_7","value":7},{"name":"mDataProp_8","value":8},
{"name":"sSearch","value":""},{"name":"bRegex","value":false},
{"name":"sSearch_0","value":""},{"name":"bRegex_0","value":false},
{"name":"bSearchable_0","value":false},{"name":"sSearch_1","value":""},
{"name":"bRegex_1","value":false},{"name":"bSearchable_1","value":false},
{"name":"sSearch_2","value":""},{"name":"bRegex_2","value":false}
];
function remove(name) {
var arr = [], len, i;
// we reset len as data.length will change after erach remove
for(i = 0, len = data.length; i < len; i++) {
if (data[i].name != name) arr.push(data[i]);
};
data = arr;
};
console.log(data);
remove('sEcho');
console.log(data);
The modern ES5 way is Array.filter:
var original = [{"name":"sEcho","value":1}, ... ];
var filtered = original.filter(function(val, index, array) {
var n = val.name;
return n !== 'sEcho' && n !== 'mDataProp_1' && n !== 'sSearch';
});
I think you'll need to create a function that can search and then remove them, something like
function deleteByName(needle, haystack) {
for(i in haystack) {
if ( haystack[i].name == needle) {
haystack.splice(i,1);
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Easiest way to find duplicate values in a JavaScript array
Javascript array sort and unique
I have the following array
var output = new array(7);
output[0]="Rose";
output[1]="India";
output[2]="Technologies";
output[3]="Rose";
output[4]="Ltd";
output[5]="India";
output[6]="Rose";
how can i remove the duplicate elements in above array.Is there any methods to do it?
You can write a function like this
function eliminateDuplicates(arr) {
var i,
len=arr.length,
out=[],
obj={};
for (i=0;i<len;i++) {
obj[arr[i]]=0;
}
for (i in obj) {
out.push(i);
}
return out;
}`
Check this here
Maybe more complex than you need but:
function array_unique (inputArr) {
// Removes duplicate values from array
var key = '',
tmp_arr2 = {},
val = '';
var __array_search = function (needle, haystack) {
var fkey = '';
for (fkey in haystack) {
if (haystack.hasOwnProperty(fkey)) {
if ((haystack[fkey] + '') === (needle + '')) {
return fkey;
}
}
}
return false;
};
for (key in inputArr) {
if (inputArr.hasOwnProperty(key)) {
val = inputArr[key];
if (false === __array_search(val, tmp_arr2)) {
tmp_arr2[key] = val;
}
}
}
return tmp_arr2;
}
Code taken from: http://phpjs.org/functions/array_unique:346
You can remove dups from an array by using a temporary hash table (using a javascript object) to keep track of which images you've already seen in the array. This works for array values that can be uniquely represented as a string (strings or numbers mostly), but not for objects.
function removeDups(array) {
var index = {};
// traverse array from end to start
// so removing the current item from the array
// doesn't mess up the traversal
for (var i = array.length - 1; i >= 0; i--) {
if (array[i] in index) {
// remove this item
array.splice(i, 1);
} else {
// add this value to index
index[array[i]] = true;
}
}
}
Here's a working example: http://jsfiddle.net/jfriend00/sVT7g/
For sizable arrays, using an object as a temporary index will be many times faster than a linear search of the array.
First of all, you'll want to use the array literal (var output = []) to declare your array. Second, you'll want to loop through your array and store all the values in a second array. If any value in the first array matches a value in the second array, delete it and continue looping.
Your code would look like this:
var output = [
"Rose",
"India",
"Technologies",
"Rose",
"Ltd",
"India",
"Rose"
]
var doubledOutput = [];
for(var i = 0; i < output.length; i++) {
var valueIsInArray = false;
for(var j = 0; j < doubledOutput.length; j++) {
if(doubledOutput[j] == output[i]) {
valueIsInArray = true;
}
}
if(valueIsInArray) {
output.splice(i--, 1);
} else {
doubledOutput.push(output[i]);
}
}
Please note, the above code is untested and may contain errors.
I have an array which looks like this :
selected_products[0]=["r1","7up",61,"Albertsons"]
selected_products[1]=["r3", "Arrowhead",78,"Arrowhead "]
selected_products[2]=["r8", "Betty Crocker Cake Mix (Variety)",109,"Arrowhead "]
...
how can I search for an item in this array according to the first entry in each item (r1,r2,..)
the array is huge I am looking for a fast an effective way to get results from this array
I used the JQuery function jQuery.inArray but it couldn't find any thing in my array , I used it this way :
alert($.inArray(["r1","7up",61,"Albertsons"],selected_products))// it returns -1
alert($.inArray("r1",selected_products))//this also returns -1
If you want it to be fast, you'll want a for loop so that you can break the loop when the match is found.
var result;
for( var i = 0, len = selected_products.length; i < len; i++ ) {
if( selected_products[i][0] === 'r1' ) {
result = selected_products[i];
break;
}
}
Of course this assumes there's only one match.
If there's more than one, then you could use $.grep if you want jQuery:
var result = $.grep(selected_products, function(v,i) {
return v[0] === 'r1';
});
This will give you a new Array that is a subset of the matched items.
In a similar manner, you could use Array.prototype.filter, if you only support modern JavaScript environments.
var result = selected_products.filter(function(v,i) {
return v[0] === 'r1';
});
One other solution would be to create an object where the keys are the rn items. This should give you a very fast lookup table.
var r_table = {};
for( var i = 0, len = selected_products.length; i < len; i++ ) {
r_table[selected_products[i][0]] = selected_products[i];
}
Then do your lookups like this:
r_table.r4;
Again this assumes that there are no duplicate rn items.
So you are trying to find the index of the matched result?, well that changes the things a little bit:
var index=-1;
for(var i = 0, len = selected_products.length; i < len; i++){
if(selected_products[i][0] === "r1"){
index = i;
break;
}
}
if(index > -1){
alert(selected_products[index].join(","));//"r1,7up,61,Albertsons"
}
Note: This will return the first result matched, if you want to get an array containing a list of all indexes:
var results=[];
for(var i = 0, len = selected_products.length; i < len; i++){
if(selected_products[i][0] === "r1"){
results.push(i);
}
}
You can then call (for example) the last 'r1' matched like this selected_products[results[results.length-1]].join(",");
Just to pick up #am not i am's great input. Here is a live example. He solved it. I just wanted to give an example that it works. Hope it helps. This puts the values found from the selected value in 2 input fields.
http://jsfiddle.net/asle/ZZ78j/2/
$(document).ready(function () {
var liste = [];
liste[0] = ["First Name", "12345678", "first.name#testdomain.no"];
liste[1] = ["Second Name", "20505050", "second.nametestdomain.no"];
liste[2] = ["", "", ""];
$("#selger").change(function () {
var valg = ($(this).val());
var telefon;
var epost;
for (var i = 0, len = liste.length; i < len; i++) {
if (liste[i][0] === valg) {
telefon = liste[i][1];
epost = liste[i][2];
$("#tel").val(telefon);
$("#epost").val(epost);
break;
}
}
});
});
Try this,
// returns the index of inner array, if val matches in any array
function findIn2dArray(arr_2d, val){
var indexArr = $.map(arr_2d, function(arr, i) {
if($.inArray(val, arr) != -1) {
return 1;
}
return -1;
});
return indexArr.indexOf(1);
}
function test(){
alert(findIn2dArray(selected_products, 'r8'));
}
You might wanna consider not doing these things in Javascript but in a server sided language (PHP/Java/.NET). In this way you:
Won't have problems with browser incapabilities (Mostly IE errors)
Shorter Javascript code and therefore faster to load.
Your site also works with Javascript turned off.
An example how to do this in PHP:
<?php
function search($array, $key, $value)
{
$results = array();
if (is_array($array))
{
if (isset($array[$key]) && $array[$key] == $value)
$results[] = $array;
foreach ($array as $subarray)
$results = array_merge($results, search($subarray, $key, $value));
}
return $results;
}
?>
You may create index object { r1: 1, r2: 2,..., < search key >: < element index >, ...} and use it for searching.