Ok, so I want to return the elements that are present in both provided arrays having the same index location.
exe1 = [A,B,C,D,N]
exe2 = [B,D,C,A,T]
it should return only C
I've tried looping them by nested loops but doesn't work, here is what I've tried:
let testing = []
for (let i = 0; i < exe1.length; i++){
for(let j = 0; j < exe2.length; j++){
if(exe1[i] === exe2[j]){
testing.push(exe1[i])
}
}
};
return testing;
mind the names of the arrays, please
You can use a simple filter to only include values in exe1 that have the same value at the same index of exe2.
const exe1 = ['A','B','C','D','N'];
const exe2 = ['B','D','C','A','T'];
const testing = exe1.filter((val, i) => val === exe2[i]);
console.log(testing)
If you want to create a function that can do this and the datatypes are primitives you can do something like this. Just a loop that goes through each index, checks both arrays, and returns the value that is the same.
const exe1 = ["A","B","C","D","N"];
const exe2 = ["B","D","C","A","T"];
function getElementsThatAreTheSame(arr1, arr2) {
const minLength = Math.min(arr1.length, arr2.length);
const sameArray = [];
for (let i = 0; i < minLength; i++) {
const item1 = arr1[i];
const item2 = arr2[i];
if (item1 == item2) sameArray.push(item1);
}
return sameArray;
}
const sameItems = getElementsThatAreTheSame(exe1, exe2);
console.log(sameItems)
However you could also use the filter method to accomplish this pretty easily as follows:
const exe1 = ["A","B","C","D","N"];
const exe2 = ["B","D","C","A","T"];
const sameArr = exe1.filter((e, i) => exe2[i] == e);
console.log(sameArr);
the filter method will take a function as an argument to which is passed the element in the array and the index of that element. We can just check the second array at that index and make sure it is the same element.
Both these approaches will not verify if it is two objects which have the same content, but are different objects. i.e. {foo: "bar"} !== {foo: "bar"}
Related
I have a set of data which is nested arrays, these arrays may be empty or they may infact contain an ID, if one of the arrays ID's matches the ID im comparing it with, I want to take all of the data inside that array which matched and assign it to a variable to be used...
example:
data = [[],[],[],[],[],[],[],[],[{"id":"123","name":"DARES HOUSE 2019","startDate":null,"endDate":null,"country":null,"city":null,"type":"Event","members":null}],[],[],[],[],[],[],[],[],[],[],[]]
id = 123
matchedArray =
for (var i = 0; i < potentialEvents.length; i++) {
for (var j = 0; j < potentialEvents[i].length; j++) {
if (id === potentialEvents[i].id) {
return;
}
}
}
console.log(matchedArray)
I'm trying to have it so matchedArray will be the array with thhe matched IDs!!
if you can help, thank you a lot!
You can do this with a combination of .map, .filter and .flat
var data = [[],[],[],[],[],[],[],[],[{"id":"123","name":"DARES HOUSE 2019","startDate":null,"endDate":null,"country":null,"city":null,"type":"Event","members":null}],[],[],[],[],[],[],[],[],[],[],[]]
var id = 123;
var matchedArray = data.map( arr => {
return arr.filter(x => x.id == id);
}).flat();
console.log(matchedArray);
You can use Array#filter method to filter the inner array and Array#flatMap method to concatenate filtered array into one.
let data = [[],[],[],[],[],[],[],[],[{"id":"123","name":"DARES HOUSE 2019","startDate":null,"endDate":null,"country":null,"city":null,"type":"Event","members":null}],[],[],[],[],[],[],[],[],[],[],[]];
let id = 123;
let matchedArray = data.flatMap(arr => arr.filter(obj => obj.id == id))
console.log(matchedArray)
I'd recommend to use .some rather then .filter/.map/.flatMap. The main benefit is that it allows to stop traversing array when element is found.
On big arrays with a lot of data it will be more efficient (≈50 times faster): jsperf test
const data = [[],[],[],[],[],[],[],[],[{"id":"123","name":"DARES HOUSE 2019","startDate":null,"endDate":null,"country":null,"city":null,"type":"Event","members":null}],[],[],[],[],[],[],[],[],[],[],[]]
const id = 123;
let matchedArray = null;
data.some((a) => {
return a.some((v) => {
if (v != null && v.id == id) {
matchedArray = a;
return true;
}
});
});
console.log(matchedArray);
I have Array below and attached output.
`var
arrayData=['cat','mat','tac','hiller','mamaer','llerih','eramam'];
output : [[cat,tac], [mat], [hiller,llerih], [mamaer,erama]];`
Want to extract common letter in an array and store in new array.
i was trying to implement using array.reducer.
You can do this with Map and a simple loop. The idea is you record each word by creating a "key" from the sum of their character code and length of the word.
Used Array#Reduce to sum the words character codes.
i.e.:
//sum of each letter's character code using reduce
const res1 = "test".split("").reduce((a,c)=>a+c.charCodeAt(), 0);
const res2 = "ttes".split("").reduce((a,c)=>a+c.charCodeAt(), 0);
const l = "test".length;
const key1 = `${l}_${res1}`;
const key2 = `${l}_${res2}`;
console.log(key1, key2, key1 === key2); //4_448 4_448 true
i.e. (without reduce and with for loop):
function sum(word){
let s = 0;
for(let i = 0; i < word.length; i++){
s += word[i].charCodeAt();
}
return s
}
//sum of each letter's character code using reduce
const res1 = sum("test");
const res2 = sum("ttes");
const l = "test".length;
const key1 = `${l}_${res1}`;
const key2 = `${l}_${res2}`;
console.log(key1, key2, key1 === key2); //4_448 4_448 true
Recording the length of the word adds an extra level of security incase two different words of lengths different had the same sum
Full Solution:
const data = ['cat','mat','tac','hiller','mamaer','llerih','eramam'];
const m = new Map();
for(let i = 0; i < data.length; i++){
const word = data[i];
const sum = word.split("").reduce((a,c)=>a+c.charCodeAt(), 0);
const key = `${word.length}_${sum}`;
m.set(key, [word].concat(m.get(key)||[]));
}
const res = Array.from(m.values());
console.log(res);
I solved it with a different way, I sorted them, grouped them then displayed them by index.
var arrayData=['cat','mat','tac','hiller','mamaer','llerih','eramam'];
var sortedArrayData = arrayData.map(itm => itm.split('').sort((a,b) => a>b).join(''));
var data = {};
sortedArrayData.forEach((itm, indx) => {
if(!data[itm]) data[itm] = [];
data[itm].push(indx)
});
var result = Object.keys(data).map(key => {
return data[key].map(it => arrayData[it])
})
console.log(result)
try it here
I have an empty array which i try to add unique objects (checkedAccounts) in a for loop. I log the unique objects in a console so i can confirm they are all unique. funny thing is, after the loop my array repeats the same value of the last index.
So in a case of adding [1,2,3] to the empty array inside a for loop,
instead of getting [1,2,3] i get [3,3,3]
find below my 2 different approaches that didnt work
//Approach 1
let finalAccounts:any[] = [];
let item:any = this.productModel;
let i:number = 0;
for(i = 0; i < checkedAccounts.length; i++){
item.accountNo = checkedAccounts[i].accountNo;
item.accountName = checkedAccounts[i].accountName;
item.accountType = checkedAccounts[i].accountType;
finalAccounts[i] = item;
console.log('item in loop ' + i, item);
console.log('Final acounts in loop ' + i, finalAccounts);
}
console.log('Final Accounts', finalAccounts);
//Approach 2
let finalAccounts:any[] = [];
let item:any = this.productModel;
for(let account of checkedAccounts){
temp.accountNo = account.accountNo;
temp.accountName = account.accountName;
temp.accountType = account.accountType;
finalAccounts.push(temp);
console.log('temp'+checkedAccounts.indexOf(account),temp);
}
You need to ensure that you have a fresh copy of the item in each loop iteration. Using the syntax below, we can create a shallow copy. Try this:
for(i = 0; i < checkedAccounts.length; i++){
let item:any = {...this.productModel};
item.accountNo = checkedAccounts[i].accountNo;
finalAccounts.push(item);
}
you can't share instance inside foreach while you push to a array i.e make it independent.
couple of observations
1) If you want to use any(strictly avoid, use it only if you are not sure about type) then there is no point using let item:any = {...this.productModel} you can simply achive same using let item:any = {}
2) preferable way will be typeScript way using interfaces
Code:
finalAccounts: IntTest[] = [];
export interface productModel {
accountNo: string;
address?: string;
}
for (i = 0; i < checkedAccounts.length; i++) {
let item: IntTest = {
accountNo: checkedAccounts[i].accountNo
};
finalAccounts.push(item);
}
This javascript code tries to use the array.filter for better performance instead of the for loop "I guess". Any way, the results are not the same, when it was expected to be.
It tries to find out the names of students who are included in the searchWords array.
Any ideas why?thx
let searchWords = ['john','matt','marry'];
let students = ['matt','jack'];
let names = [];
for (let i = 0; i < searchWords.length; i++) {
if (students.indexOf(searchWords[i]) !== -1) {
names.push(searchWords[i]);
}
}
console.log(names.length); // => 1 "correct"
names = [];
names = searchWords.filter(x => students.filter(y => students.indexOf(x) !== -1));
console.log(names.length); // => 3 "incorrect"
The filter line has essentially added another loop. It should be
names = searchWords.filter(x => students.indexOf(x) !== -1);
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
}