I trying to loop through an array of arrays, and compare the elements with each-other in-order to find the common elements. so lets say if we have var arr = [[1,2,3],[4,2,5]]; I want to first compare [i][i] and [i+1][i], [i][i+1] and [i+1][i+1] and [i][i+2] and [i+1][i+2] and so on. here is my code:
function sym(args) {
var fullArr = [];
var finalArr = [];
// store the arguments inside a single array
for (var count = 0; count < arguments.length; count ++) {
fullArr[count] = arguments[count];
}
// loop through finalArr[];
for (var i = 0; i < fullArr.length; i++) {
if (fullArr[i][i] == fullArr[i++][i++]) {
// if the element matches (it is a common element)
// store it inside finalArr
finalArr[i] = fullArr[i];
}
}
return finalArr;
}
sym([1, 2, 3], [5, 2, 1, 4]);
problem: when I run the code instead of an array containing the matching element, I get an empty array
You first have to iterate over one array and see if the other array includes the value you have specified.
My answer is similar to a nested for loop in that the includes method does exactly that. It takes in as a parameter an element and checks if the array which called it contains said element. In order to do that it must iterate through all elements in the array in the worst case.
My answer also assumes that you only want to count duplicate matches once.
function sym(args) {
var fullArr = [];
var finalArr = [];
// store the arguments inside a single array
for (var count = 0; count < arguments.length; count ++) {
fullArr[count] = arguments[count];
}
// loop through finalArr[];
//since you are comparing only two arrays in this
//example you just have to iterate over each element in the first array aka fullArr[0] and
//check if each element "e" is also in the second array aka fullArr[1]
//AND that your final output array does not already contain it.
//If both of these are true then we push the element to the output array.
fullArr[0].forEach(function(e){
if(fullArr[1].includes(e) && !finalArr.includes(e)) finalArr.push(e);
});
return finalArr;
}
sym([1, 2, 3], [5, 2, 1, 4]);
However if you want to check if a particular element exists in all collections of an n length array then I would propose something like this:
function sym(args) {
var fullArr = [];
var finalArr = [];
// store the arguments inside a single array
for (var count = 0; count < arguments.length; count ++) {
fullArr[count] = arguments[count];
}
var newArr = fullArr[0].reduce( function(prev, e1) {
if(prev.indexOf(e1) < 0 && fullArr.every( function(arr){
return arr.indexOf(e1) > -1;
})){
return [...prev, e1];
}else{
return prev;
};
},[]);
alert(newArr);
return newArr;
}
sym([1,1, 2, 3,4], [5, 2, 1, 4], [4,1,2, 5]);
You can iterate over the first array and check if any of its values are common through all the other arrays.
function sym() {
var common = [];
for (var i=0; i<arguments[0].length; i++) {
var isCommon = common.indexOf(arguments[0][i]) === -1; // first check if its not already exists in the common array
for (var j=1; j<arguments.length && isCommon; j++) {
isCommon = arguments[j].indexOf(arguments[0][i]) > -1
}
if (isCommon) common.push(arguments[0][i])
}
return common;
}
of course you can improve it by iterating over the smallest array.
In your code, when the following line executes, you also increment the value of i which is your control variable:
if (fullArr[i][i] == fullArr[i++][i++])
Thus, this is how your i variable gets incremented in each iteration:
Iteration #1: i = 0
Iteration #2: i = 3
- you get i+2 from the line that I mentioned above, +1 more from the increment that you specify in the final condition of the for loop
Therefore, even after the first iteration, your function will return an empty array on your particular scenario, as you are passing an array of length 3, and the for loop ends after i = 0 on the first iteration.
Even if the loop would go on, it would return an index out of bounds exception because your array of length 3 would not have an array[3] element.
For example, if you want to compare just two arrays, as in your scenario, you need to loop through each of them and compare their elements:
function sym(array1, array2) {
var results = [];
for (var i = 0; i < array1.length; i++) {
for (var j = 0; j < array2.length; j++) {
if(array1[i] === array2[j]) {
if(results.indexOf(array1[i]) === -1) {
results.push(array1[i]);
}
}
}
}
return results;
}
sym([1, 2, 3], [5, 2, 1, 4]);
I have also built a solution that returns the intersection of the arrays that you provide as the parameters for the function, regardless of how many arrays there are:
function sym(args) {
var paramSet = Array.prototype.slice.call(arguments);
var counterObject = {};
var results = [];
paramSet.forEach(function (array) {
// Filter the arrays in order to remove duplicate values
var uniqueArray = array.filter(function (elem, index, arr) {
return index == arr.indexOf(elem);
});
uniqueArray.forEach(function (element) {
if (Object.prototype.hasOwnProperty.call(counterObject, element)) {
counterObject[element]++;
} else {
counterObject[element] = 1;
}
});
});
for (var key in counterObject) {
if (counterObject[key] === paramSet.length) {
results.push(parseInt(key));
}
}
return results;
}
sym([1, 2, 3, 3, 3], [5, 2, 1, 4], [1, 7, 9, 10]);
The above code will return [1] for the example that I provided, as that is the intersection of all 3 arrays.
Related
This question already has answers here:
How can I remove a specific item from an array in JavaScript?
(142 answers)
Closed 1 year ago.
How can I check whether an array contains a value, and if so, remove it?
PS: For this exercise, I'm not allowed to use anything more than than .pop, .push and .length array functions.
My logic is the following: if the specified value is within the array, reorder the array so that the last element of it will contain this value, then remove it with .pop. But how can I find this value and reorder it without using anything more than those array functions I specified above?
This is what I managed to come up with so far:
let array_1 = [1,2,3];
if (array_1 == 2){
//reorder somehow
array_1.pop();
}
console.log(array_1);
Using this approach, you are not creating a new array but modifying it. It uses .pop().
let array_1 = [1, 2, 3];
// Iterate all array
for (let i = 0; i < array_1.length; i++) {
// While there is a 2 element in the actual index, move all elements (from i index) to the previous index
while(array_1[i] === 2) {
for (let j = i; j < array_1.length - 1; j++) {
array_1[j] = array_1[j + 1];
}
// Now remove the last element (since we move all elements to the previous index)
array_1.pop();
}
}
console.log(array_1);
Here a snippet so you can try it
let array_1 = [1, 2, 3, 4, 2, 5, 2, 6, 2];
for (let i = 0; i < array_1.length; i++) {
while(array_1[i] === 2) {
for (let j = i; j < array_1.length - 1; j++) {
array_1[j] = array_1[j + 1];
}
array_1.pop();
}
}
console.log(array_1);
This would mantain the order of the array, but without the "2" elements.
Here's another option using pop
const filter = (array, target) => {
const newArray = [];
let tmp;
while(tmp = array.pop()) {
if (tmp !== target) {
newArray.push(tmp)
}
}
console.log(newArray)
return newArray;
}
filter([1,2,3,4], 2) // [4, 3, 1] Note that it reversed the order of the array!
If you are limited to pop, push and length, you can loop over all elements, check if a given element matches the value you are looking for, and add them to a new array using push.
let array_1 = [1,2,3];
let newArray = [];
for (let i = 0; i < array_1.length; i++) {
if (array_1[i] !== 2) {
newArray.push(array_1[i]);
}
}
console.log(newArray);
// using splice
// splice(indexStart, how many, replace with)
// example :
let arr = [0,1,2,3,4,5];
// remove at index 1
arr.splice(1,1);
console.log( arr );
// replace at index 1
arr.splice(1,1,"new 1");
console.log( arr );
// merge index 2 and 3
arr.splice(2,2,"merge 2 and 3");
console.log( arr );
// create 2 new items start at index 2
arr.splice(2,2,"new 2", "new 3");
console.log( arr );
I have a function which creates an array of subarrays. It takes three parameters: the number of subarries to create within the array (numSub), the number of times the desired value occurs within each subarray (numValue), and the desired value (value).
For example, if I were to call the function with (3, 2, test), I would want the following output:
Array [Array ["test", "test"], Array ["test", "test"], Array ["test", "test"]]
Here is the function I have written:
function subarrs(numSub, numValue, value) {
let arr = [];
for (let i = 0; i < numSub; i++) {
arr.push([]);
}
arr.forEach(function(sub) {
sub.fill(value, 0, numValue - 1);
});
return arr;
}
console.log(subarrs(3, 2, 'test'));
I have looped through the numSub variable and inserted an array into arr for each iteration. This was successful. (Array [Array [], Array [], Array []])
I then use a forEach loop to fill each sub-array with value beginning at index 0 and ending at index numValue - 1 (because the second occurrence of the value would actually be at index 1.)
The function does not work as intended, however. Rather than the aforementioned desired output, I receive this:
Array [Array [], Array [], Array []]
You can use fill on an array that has received the right length, like Array(numValue).fill(numValue). Here is how you could do it:
function subarrs(numSub, numValue, value) {
return Array.from({length: numSub}, () => Array(numValue).fill(value));
}
console.log(subarrs(3, 2, 'test'));
You are filling an empty array. It's still an empty array (nothing to fill).
You should construct the array of some length:
arr.push(new Array(numValue));
Complete:
function subarrs(numSub, numValue, value) {
let arr = [];
for (let i = 0; i < numSub; i++) {
arr.push(new Array(numValue));
}
arr.forEach(function(sub) {
sub.fill(value);
});
return arr;
}
console.log(subarrs(3, 2, 'test'));
Array.fill() only modifies array values. It does not add new ones. Use push again instead
function subarrs(numSub, numValue, value) {
let arr = [];
for (let i = 0; i < numSub; i++) {
arr.push([]);
}
arr.forEach(function(sub) {
for (let j = 0; j < numValue; j++) {
sub.push(value);
}
});
return arr;
}
console.log(subarrs(3, 2, 'test'));
You can use .push method to add value into your array instead .fill, see working demo :
function subarrs(numSub, numValue, value) {
let arr = [];
for (let i = 0; i < numSub; i++) {
arr.push([]);
for (let j = 0; j < numValue; j++) {
arr[i].push(value);
}
}
return arr;
}
console.log(subarrs(3, 2, 'test'));
fill will only work on indexes that already exist and its second parameter in your case should be the length of the array (which is the default value) and not length - 1. You can see it here:
let myEmptyArray = [];
let myFullArray = [1, 2, 3, 4];
myEmptyArray.fill(0, 0, 4);
myFullArray.fill(0, 0, 4);
console.log(myEmptyArray, myFullArray)
You could push an Array with the necessary slots already in place with new Array(numValue). Something like this:
function subarrs(numSub, numValue, value) {
let arr = [];
for (let i = 0; i < numSub; i++) {
arr.push(new Array(numValue));
}
arr.forEach(function(sub) {
sub.fill(value);
});
return arr;
}
console.log(subarrs(3, 2, 'test'));
If you have es2015+ You can do it easily :
const subarrs = (length, subLength, value) =>
[...Array(length)].map(() => [...Array(subLength)].fill(value));
subarrs(3, 2, 'test');
(Edited) after the first comment
I've been trying and searching how to loop through the params to check if those already exist in an array, i haven't got it fully working but when there is a duplicate value it dose not return at all.
The idear is pass multiple values is param then loop through those vals and only push if it dose not exist in the array.
var arr = [7,3,1];
function pushNew(obj) {
var prams = obj;
for(var k = 0; k < obj.length; k++){
for (var i = 0; i < arr.length; i++) {
if (arr[i] == prams[k]) {
return;
}
}
array.push(prams[k]);
}
// console.info(arr);
}
pushNew([2,7,4]);
A short and more modern way to just get all the unique values is to use Array.from with Set. A Set is an array-like structure that will only hold unique values. Array.from converts an array-like structure into a real array.
In your case, you can just concat both arrays, pass them to Set to remove the duplicates, and use Array.from to convert it back to a regular array.
var arr1 = [1, 2, 3, 4, 5];
var arr2 = [3, 4, 5, 6, 7];
var result = Array.from(new Set(arr1.concat(arr2)));
document.write(JSON.stringify(result));
Actually, your existing code nearly works.
You can set a flag if you find a match in the inner loop and instead of return you should use break to escape the loop. Then use push after the inner loop if a match wasn't found. Also, there is no need for both obj and prams (which I've renamed to params), so:
var arr = [7,3,1];
function pushNew(params) {
var found;
for(var k=0; k<params.length; k++){
// Set found to initial value on each outer loop
found = false;
for (var i=0; i<arr.length; i++) {
// If find match, set flag and break from loop (for efficiency)
if (arr[i] == params[k]) {
found = true;
break;
}
}
// If match not found, push into arr
if (!found) arr.push(params[k]);
}
}
pushNew([7,2])
document.write(arr); // 7,3,1,2
If you want efficient code, consider creating an index and using in:
var arr = [7,3,1];
function addParams(params) {
var index = arr.reduce(function(acc, v) {
acc[v] = true;
return acc;
},{});
params.forEach(function(v) {
if (!(v in index)) arr.push(v);
});
}
addParams([7,3,2]);
document.write(arr);
You can use indexOf to validate if element is present in an array. forEach is another array method which works like loop.
var arr = [7,3,1];
function pushNew(obj) {
//var prams = obj;
obj.forEach(function(item){ // iterate through each element
if(arr.indexOf(item) == -1){ //indexOf return -1 is element is not present in an array
arr.push(item)
}
})
console.log(arr);
}
pushNew([2,7,4]);
Working Jsfiddle
var arr = [7, 3, 1];
function pushNew(obj) {
for (var k = 0; k < obj.length; k++) {
if (arr.indexOf(obj[k]) == -1) {
arr.push(obj[k]);
}
}
}
pushNew([2, 7, 4]);
You can use _.union function of lodash.
_.union([2, 1], [4, 2], [1, 2]);
// → [2, 1, 4]
I am working on a code where I need to reverse certain no of elements in an array and rest should remain same. For example is an array has values of 1,2,3,4,5,6 and I have to reverse 4 elements of it then output should be 4,3,2,1,5,6. I am using below code to achieve this but getting error, please suggest.
function reverseArray(n, a) {
var interimArray1 = [];
//var interimArray2=[];
//var finalArray=[];
for (var i < n; i >= 0; i--) {
interimArray1.push[a[i]];
}
for (var i = n; i < a.length; i++) {
interimArray1.push[a[i]];
}
for (var i = 0; i < interimArray1.length; i++) {
console.log(interimArray1[i]);
}
}
var arr = [1, 2, 3, 4, 5, 6];
var num = 4;
reverseArray(num, arr);
The error in your code is that you intend to call the push method on a[i] like so:
interimArray1.push(a[i]);
but instead you write:
interimArray1.push[a[i]];
You make that mistake twice. To give arguments to the push method, you must use round parenthesis ().
With that fixed, you will see that your code works perfectly.
You can use Array#slice, Array#splice as follow.
function partialReverse(arr, num, from = 0) {
var slicedArr = arr.slice(from, num + from);
arr.splice(from, num); // Remove `num` items from array
arr.splice(from, 0, ...slicedArr.reverse()); // Add `num` reversed items
return arr;
}
var arr = [1, 2, 3, 4, 5, 6];
console.log(partialReverse(arr, 4, 0)); // Reverse four items from `arr` starting from 0th index
console.log(partialReverse(arr, 4, 1)); // Reverse four items from `arr` starting from 1st index
Lots of hints but you seem to be missing them. ;-)
You need to assign an initial value to i, so:
for (var i = n; ... )
===========^
Also, you need to use () to call functions, not [], so:
interimArray1.push(a[i]);
==================^====^
Same in the following for block. Otherwise, the code works though it's more verbose than it needs to be.
This is working :
I'm sure there are faster ways of doing it. Also, it will only work for elements at the beginning of the array but you can adjust the function for what you want to achieve.
var reverseArray = function(arr,elementsToReverse) {
var tempArrayRev = [];
var tempArray = [];
for (var i=0;i<arr.length;i++) {
if (i < elementsToReverse) {
tempArrayRev[i] = arr[i];
} else {
tempArray.push(arr[i]);
}
}
return tempArrayRev.reverse().concat(tempArray);
}
var array = [1,2,3,4,5,6];
document.getElementById('arrayOutput').innerHTML += reverseArray(array,4);
<div id="arrayOutput">Array :<br></div>
This is the answer you can test it.
function reverseArray(n, a) {
var interimArray1 = [];
for (var i = 0; i < a.length; i++) {
interimArray1.push(a[i]);
}
for (var i = num; i >=0; i--) {
interimArray1[i-1] = a[n - i];
}
for (var i = 0; i < interimArray1.length; i++) {
console.log(interimArray1[i]);
}
}
var arr = [1, 2, 3, 4, 5, 6];
var num = 4;
reverseArray(num, arr);
You could use something like this.
function reverseArray(n, arrIn) {
// Splice splits the array in 2 starting at 0 index going n long
var arrOut = arrIn.splice(0,n);
// reverse is pretty straight forward
arrOut = arrOut.reverse();
// Concat joins the two together
return arrOut.concat(arrIn);
}
I have an array and an array of objects. I want to search each value in the array in the array of objects and if it doesnt exist, I want to remove the value from the array.
var arr= [1,2,3,4];
var recs = [{id:1},{id:2},{id:3}]; //4 doesnt exist in recs, remove from arr
//arr = [1,2,3];
Heres my attempt. Obviously does not work. I am not sure how I can compare each arr index with all the values in recs before moving on the next arr index:
var arr= [1, 2, 3, 4], index;
var recs = [{a:1},{a:2},{a:3}];
for(var i = 0; i<arr.length; i++){
for(var val in recs[i]){
if(arr[i] != recs[i][val]){
index = arr.indexOf(arr[i]);
arr.splice(index, 1);
}
}
}
thank you!!
If you are okay with leaving your original array instance alone and creating a new one (essentially treating it as immutable)
var newArr = arr.filter(function(num) {
return !recs.every(function(obj) {
return obj.a !== num;
});
});
Detail of the methods used: Array.filter is passed a function, runs that function on each element inside, and then returns a new array with only the elements that returned true in the function.
Array.every works a little similar, but returns a Boolean, true or false. It returns true if all of the elements of the array returned true inside of the function.
var arr= [1, 2, 3, 4];
var recs = [{a:1},{a:2},{a:3}];
// don't use var in for loops.
// Variables declared with var have function scope, so declare them at the top of your function
var i;
var j;
var value;
var found;
// iterate over the array
for (i = 0; i < arr.length; i++)
{
value = arr[i];
found = false;
// iterate over the other array
for (j = 0 ; j < recs.length ; j++)
{
// if we found what we were looking for, make a note and exit loop
if (recs[j].a == value)
{
found = true;
break;
}
}
if (!found)
{
arr.splice(i, 1);
// To compensate the loop's i++, to avoid skipping the next entry
i--;
}
}
alert(arr.join(','));