Question: I have this array that have a nested array that I want to loop to find a specific value.
arr = [['123456','234567'], ['345678']];
specificValue = '123456';
The output that I want is to find out if there's a value same with specificvalue and return this value?
I tried
arr.filter(id => id === specificValue);
Thanks for the help
Let's keep going with your attempt.
The problem is your array is nested so array.filter will not work
Use array.flat with array.filter:
let arr = [['123456','234567'], ['345678']];
let specificValue = '123456';
console.log(arr.flat().filter(i=>i==specificValue))
Try this code
const arr = [['123456','234567'], ['345678']];
const result = arr.flat(Infinity).find(val => val === "123456");
console.log(result);
You can learn more about array.flat() method here
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat
Since flat() takes a depth as an argument, to be able to search in an indefinite number of nested arrays you could try good old recursion:
const findRecursive = (array, target) => {
for (let i = 0; i < array.length; i++) {
if (array[i] === target) {
return array[i];
} else if (Array.isArray(array[i])) {
return findRecursive(array[i], target);
}
}
}
console.log(findRecursive(arr, specificValue));
EDIT: Abdelrhman Mohamed has corrected me, you can specify an indefinite amount of nested arrays using array.flat(Infinity)
Related
Do anyone understand why console.log(posArr) is printing [1,2,3] and not [0,1,2]. Im trying to push to nOfPos all the index positions of my array :)
function combinations(x) {
let arr = x.toString().split('');
console.log(arr)
let nOfPos = [];
let posArr = arr.map(x => nOfPos.push(arr.indexOf(arr[x])));
let mult = posArr.reduce((acum, item) => acum * item);
console.log(posArr);
console.log(mult);
}
combinations(123)
The problem is due to two errors in your code. Firstly push() returns the new length of the array, so that's why the mapped output contains the incremental 1,2,3....
Secondly, you need to search for x within arr, so you only need to pass x to indexOf().
With those issues corrected the code works:
function combinations(x) {
let arr = x.toString().split('');
let posArr = arr.map(x => arr.indexOf(x));
let mult = posArr.reduce((acum, item) => acum * item);
console.log(posArr);
console.log(mult);
}
combinations(123)
That being said, the purpose of posArr is a little redundant; it will always be an array of incremental values, up to the length of the string -1.
In addition, mult is redundant too as it will always be 0, as you are multiplying by 0.
You could use a 'for in' loop to get the array indexes.
let posArr = [];
for (ix in arr) {
posArr.push(ix)
}
I have two arrays.I'm trying to remove some elements from [arr] at index numbers in [removeIndex].
var removeIndex = [2,3];
var arr = [1,1,0,0,1,1,1];
for (let i = 0; i < removeIndex.length;i++){
arr.splice(removeIndex[i],1);
}
console.log(arr)
// output Array(5) [ 1, 1, 0, 1, 1 ]
//expected [ 1,1,1,1,1]
Both the 0's are at arr[2] and arr[3] position and should get removed,however the above code doesnt work.I suspect it has to do with the loop re-arranging the index numbers.Any alternate solution?
You definitely suspect correctly about why this is happening. The easiest way I can think of to do what you're after is to use the not-often-used second argument to the callback function passed to the filter method, which takes an element's index:
arr = arr.filter((elt, index) => removeIndex.indexOf(index) == -1);
You can use Array.prototype.filter()
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
and Array.prototype.includes()
The includes() method determines whether an array includes a certain element, returning true or false as appropriate.
Pass index as the second parameter to check whether that index includes or not in removeIndex. Return the element only if the current index does not exist in removeIndex array:
var removeIndex = [2,3];
var arr = [1,1,0,0,1,1,1];
arr = arr.filter((i,idx) => !removeIndex.includes(idx));
console.log(arr); //[ 1,1,1,1,1]
I would use filter and come up with this clean code:
var removeIndex = [2,3];
var arr = [1,1,0,0,1,1,1];
var newArr = arr.filter(el => el !== 0);
console.log(newArr);
// [1,1,1,1,1]
As stated in the comments, you mutate the array so the next time you loop through the array it's items will be changed and you won't have the same items at the same indexes. There is a fairly simple solution for your particular example :
var removeIndex = [2,3].sort(); // This won't work with [3,2] for example
var arr = [1,1,0,0,1,1,1];
for (let i = 0; i < removeIndex.length; i++){
arr.splice(removeIndex[i] - i, 1);
}
console.log(arr)
But I'd suggest using an immutable solution with .filter for example, like suggested in the comments
I'm getting an error message when attempting to filter a nested array in javascript. The task is to build a function that filters out any sub-arrays of the input array if they contain a specific element in them.
My current code is:
function filteredArray(arr, elem) {
let newArr = [];
newArr = [...arr];
console.log(newArr);
for (var i=0; i < newArr.length; i++) {
newArr.filter(newArr[i] => newArr[i].indexOf(elem) >= 0);
}
return newArr;}
javascript apparently doesn't like me trying to filter newArr based upon a sub-array newArr[i] because it states that the [] are unexpected tokens. What's going on here?
Using Array#filter and Array#includes you can very easily filter out Arrays that contain a specific element:
const filteredArray = (array, elem) => array.filter(subArray => !subArray.includes(elem));
let testArr = [[1,2,3,4, "a"],[1,2,3,4,8],[1,2,3,4, "a"],[1,2,3,4,5]];
console.log(filteredArray(testArr, "a"));
I'm building a search function in react-native and redux. In my action creator, I'm returning a json from Firebase. I then turn json into an array:
const myObj = snapshot.val(); //json
const array1 = Object.entries(myObj).map(function(key) {
return (key);
});
That way I can filter() through array1.
const array2 = array1.filter(
(value) => {
const element = "John Deere"; // I've hard coded the user input
return (value.indexOf(element) !== -1);
});
However, array1 is a multi-dimensional array. So, this filter() doesn't have access to the nested array. If I create an array copy1 like so, it will have access:
const copy1 = [];
const len = array1.length;
for (let i = 0; i < len; i++) {
copy1.push(array1[i][1]);
}
But then I lose access to
array1[i][0].
That index is a unique id created by Firebase. Which I need to make sure my data doesn't get all mixed up.
Is there a way to .filter() a specific index of an array (array1[i][1]), but to return the full array where that specific index matches the criteria?
(array1 [i] where array1 [i][1] matches the user input(element))
I can't just return:
array1 [i][j]
because array1 [i][0] is just a string and not an object (key value pair), so that causes an error.
Any help is much appreciated!
In the filter()
Change:
return (value.indexOf(element) !== -1);
To
return (value[specifiedIndex].indexOf(element) !== -1);
OR
return value[specifiedIndex].includes(element);
Here's what worked:
const array2 = array1.filter(
(value) => {
const element = "John Deere";
for (let i = 0; i < len; i++) {
return (value[1].make.indexOf(element) !== -1);
}
});
That is of course only going to work for the "make" key. But I'm sure it's possible to use the || operator in the filter function to include more keys.
the only way I can think to do this is to do something like:
for current array length,
for array to check length
if current array i === array to check i
true
Essentially I have the following:
arr = [[1,2], [0,3]];
When I want to add another array to this arrays: [1,2] I need to first see if it exists, if it does do not push it on to the array, if it doesn't then push it.
Is there some really simple, clean readable way to check if an array exists in an array of arrays before pushing it on to the list of elements?
Update:
it should be pretty simple, you have array:
arr = [[1,2], [0,3]];
You try and push:
[1,2]
Nothing happens.
You try and push: [4,6]. New array: [[1,2], [0,3], [4,6]];
Since the complexity is limited, a simple solution exists:
function maybePush(to, val) {
if(!to.some(function(curr) {
return curr.length !== val.length ||
curr.some(function(v, i) { return val[i] === v; });
})) {
to.push(val);
}
}
arr = [[1,2], [0,3]];
maybePush(arr, [1,2]);
maybePush(arr, [5,6]);
console.log(arr);
You'd probably want to add some guards, check that what you expect to be an array really is an array and so on (left out for clarity)...
The idea is simple, check if any of the values of the outer array is equal to the val array, using an iterative comparison.
If you know your array arr contains only integers and arrays, a simple check to see if the array matches the flattened array will indicate if the array contains inner arrays.
var arr = [1,2,3,[4,5],6];
if (JSON.stringify(arr) === JSON.stringify([].concat.apply([], arr))) {
// Does not contain an array
}
The snippet [].concat.apply([], arr) flattens the array arr.
Using underscore you can do this:
Initial approach:
var i = _.findIndex(arr, function (e) {
return (e.join(',') === arr_elem.join(','));
});
if (i === -1) {
arr.push(arr_elem);
}
EDIT Considering performance (Also read the comments here), it would be better to check array equality using a brute loop approach:
function arraysEqual(arr1, arr2) {
if(arr1.length !== arr2.length)
return false;
for(var i = arr1.length; i--;) {
if(arr1[i] !== arr2[i])
return false;
}
return true;
}
var i = _.findIndex(arr, function (e) {
return arraysEqual(arr_elem, e);
});
if (i === -1) {
arr.push(arr_elem);
}