Find an Array of Values Inside an Array
Lets say I have an array [1,2,3,8,2,3,4,5,6,7,8] and I want to find the first occurrence of the values [3,4,5,6] together, how might I do that? I can use Array.prototype.findIndex, but when I am looking for a large amount of values in a large array, it doesn't feel like the proper way to do it.
What fails:
let largeArray = [1,2,3,8,2,3,4,5,6,7,8];
let smallArray = [3,4,5,6];
//Problem: an array isn't a function
largeArray.findIndex(smallArray);
/*
Problem: always returns -1 because it checks each element
rather than looking for a group of elements.
*/
largeArray.indexOf(smallArray);
//Problem: same as using indexOf
largeArray.findIndex(item=>smallArray);
What works:
let largeArray = [1,2,3,8,2,3,4,5,6,7,8];
let smallArray = [3,4,5,6];
//Here is what works, but isn't ideal
largeArray.findIndex((item, index, arr) => {
let isTheOne = item == smallArray[0] &&
arr[index + 1] == smallArray[1] &&
arr[index + 2] == smallArray[2] &&
arr[index + 3] == smallArray[3];
return isTheOne;
});
//It returns 5, which is correct.
To Be Continued
I am currently using what works, but what if largeArray had the length of a million and smallArray had the length of 300. That would be 1 line of item == smallArray[0] &&, 298 lines of arr[index + x] == smallArray[x] &&, and 1 line of arr[index + x] == smallArray[x];. I don't want to use Array.prototype.map, Array.prototype.filter, Array.prototype.forEach, a for loop, or a while loop. This is because Array.prototype.map, Array.prototype.forEach, and the loops take a very long time to complete. I don't want to use Array.prototype.filter because that doesn't give me the index.
You were on the right track, you just want to use every() to look over the small index to check that each index matches
const largeArray = [1, 2, 3, 8, 2, 3, 4, 5, 6, 7, 8];
let smallArray = [3, 4, 5, 6];
const index = largeArray.findIndex(
(item, index, arr) =>
smallArray.every(
(n, sIndex) => n === arr[index + sIndex]
)
);
console.log(index);
You could add a check beforehand to not have to go in every... not sure what that would improve.
const index = largeArray.findIndex(
(item, index, arr) =>
item === smallArray[0] &&
smallArray.every(
(n, sIndex) => n === arr[index + sIndex]
)
);
Other approach is using strings
const largeArray = [1, 2, 3, 8, 2, 3, 4, 5, 6, 7, 8];
const smallArray = [3, 4, 5, 6];
const largeStr = largeArray.join(",");
const smallStr = smallArray.join(",");
const strIndex = largeStr.indexOf(smallStr);
const index = strIndex > -1 ? largeStr.substr(0,strIndex-1).split(",").length : -1;
console.log(index)
To figure out what is better is really based on your use case.
You can use .join to convert the arrays to strings, and use .indexOf to get the index given that you will remove the additional commas:
const getIndexOfSubArray = (arr=[], sub=[]) => {
const str = arr.join();
const subStr = sub.join();
const index = str.indexOf(subStr);
return index < 0 ? -1 : str.substr(0, index-1).split(',').length;
}
console.log( getIndexOfSubArray([1,2,3,8,2,3,4,5,6,7,8], [3,4,5,6]) );
You could iterate by hand and check the items with indexOf.
function getIndex(array, subarray) {
let p = -1,
first = subarray[0];
while ((p = array.indexOf(first, p + 1)) !== -1) {
let i = p,
complete = true;
for (const s of subarray) {
if (s !== array[i++]) {
complete = false;
break;
}
}
if (complete) return p;
}
return -1;
}
console.log(getIndex([1, 2, 3, 8, 2, 3, 4, 5, 6, 7, 8], [3, 4, 5, 6])); // 5
Here is a simple approach to this problem:
let largeArray = [1, 2, 3, 8, 2, 3, 4, 5, 6, 7, 8];
let smallArray = [3, 4, 5, 6];
let s = 0,
i = 0,
j = 0;
let SLen = smallArray.length,
LLen = largeArray.length;
while (i < LLen && j < SLen && SLen - j <= LLen - i) {
if (j == 0) {
s = i;
}
if (largeArray[i] == smallArray[j]) {
j++;
} else {
j = 0;
i = s;
}
i++;
}
let index = i - j;
if (j == SLen) {
console.log(`found at index ${index}`);
} else {
console.log('not found');
}
Related
Given an array [[1, 7, 3, 8],[3, 2, 9, 4],[4, 3, 2, 1]],
how can I find the sum of its repeating elements? (In this case, the sum would be 10.)
Repeated values are - 1 two times, 3 three times, 2 two times, and 4 two times
So, 1 + 3 + 2 + 4 = 10
Need to solve this problem in the minimum time
There are multiple ways to solve this but time complexity is a major issue.
I try this with the recursion function
How can I optimize more
`
var uniqueArray = []
var sumArray = []
var sum = 0
function sumOfUniqueValue (num){
for(let i in num){
if(Array.isArray(num[i])){
sumOfUniqueValue(num[i])
}
else{
// if the first time any value will be there then push in a unique array
if(!uniqueArray.includes(num[i])){
uniqueArray.push(num[i])
}
// if the value repeats then check else condition
else{
// we will check that it is already added in sum or not
// so for record we will push the added value in sumArray so that it will added in sum only single time in case of the value repeat more then 2 times
if(!sumArray.includes(num[i])){
sumArray.push(num[i])
sum+=Number(num[i])
}
}
}
}
}
sumOfUniqueValue([[1, 7, 3, 8],[1, 2, 9, 4],[4, 3, 2, 7]])
console.log("Sum =",sum)
`
That's a real problem, I am just curious to solve this problem so that I can implement it in my project.
If you guys please mention the time it will take to complete in ms or ns then that would be really helpful, also how the solution will perform on big data set.
Thanks
I would probably use a hash table instead of an array search with .includes(x) instead...
And it's also possible to use a classical for loop instead of recursive to reduce call stack.
function sumOfUniqueValue2 (matrix) {
const matrixes = [matrix]
let sum = 0
let hashTable = {}
for (let i = 0; i < matrixes.length; i++) {
let matrix = matrixes[i]
for (let j = 0; j < matrix.length; j++) {
let x = matrix[j]
if (Array.isArray(x)) {
matrixes.push(x)
} else {
if (hashTable[x]) continue;
if (hashTable[x] === undefined) {
hashTable[x] = false;
continue;
}
hashTable[x] = true;
sum += x;
}
}
}
return sum
}
const sum = sumOfUniqueValue2([[1, 7, 3, 8],[[[[[3, 2, 9, 4]]]]],[[4, 3, 2, 1]]]) // 10
console.log("Sum =", sum)
This is probably the fastest way...
But if i could choose a more cleaner solution that is easier to understand then i would have used flat + sort first, chances are that the built in javascript engine can optimize this routes instead of running in the javascript main thread.
function sumOfUniqueValue (matrix) {
const numbers = matrix.flat(Infinity).sort()
const len = numbers.length
let sum = 0
for (let i = 1; i < len; i++) {
if (numbers[i] === numbers[i - 1]) {
sum += numbers[i]
for (i++; i < len && numbers[i] === numbers[i - 1]; i++);
}
}
return sum
}
const sum = sumOfUniqueValue2([[1, 7, 3, 8],[[[[[3, 2, 9, 4]]]]],[[4, 3, 2, 1]]]) // 10
console.log("Sum =", sum)
You could use an objkect for keeping trak of seen values, like
seen[value] = undefined // value is not seen before
seen[value] = false // value is not counted/seen once
seen[value] = true // value is counted/seen more than once
For getting a value, you could take two nested loops and visit every value.
Finally return sum.
const
sumOfUniqueValue = (values, seen = {}) => {
let sum = 0;
for (const value of values) {
if (Array.isArray(value)) {
sum += sumOfUniqueValue(value, seen);
continue;
}
if (seen[value]) continue;
if (seen[value] === undefined) {
seen[value] = false;
continue;
}
seen[value] = true;
sum += value;
}
return sum;
},
sum = sumOfUniqueValue([[1, 7, 3, 8], [3, 2, 9, 4], [4, 3, 2, 1]]);
console.log(sum);
Alternatively take a filter and sum the values. (it could be more performat with omitting same calls.)
const
data = [[1, 7, 3, 8], [3, 2, 9, 4, 2], [4, 3, 2, 1]],
sum = data
.flat(Infinity)
.filter((v, i, a) => a.indexOf(v) !== a.lastIndexOf(v) && i === a.indexOf(v))
.reduce((a, b) => a + b, 0);
console.log(sum);
You can flatten the array, filter-out single-instance values, and sum the result:
const data = [
[ 1, 7, 3, 8 ],
[ 3, 2, 9, 4 ],
[ 4, 3, 2, 1 ]
];
const numbers = new Set( data.flat(Infinity).filter(
(value, index, arr) => arr.lastIndexOf(value) != index)
);
const sum = [ ...numbers ].reduce((a, b) => a + b, 0);
Another approach could be the check the first and last index of the number in a flattened array, deciding whether or not it ought to be added to the overall sum:
let sum = 0;
const numbers = data.flat(Infinity);
for ( let i = 0; i < numbers.length; i++ ) {
const first = numbers.indexOf( numbers[ i ] );
const last = numbers.lastIndexOf( numbers[ i ] );
if ( i == first && i != last ) {
sum = sum + numbers[ i ];
}
}
// Sum of numbers in set
console.log( sum );
function revertNumbers(...numberArray) {
let rev = [];
for(let i = 0; i <numberArray.length; i++)
{
rev.push(numberArray[i])
}
return rev.reverse();
}
console.log("revertNumbers", revertNumbers(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) === "9,8,7,6,5,4,3,2,1,0");
Can you please show me the how to reverse number in this code that the statement will be true? Also without using .reverse method. Is it possible to make it in another for loop by just changing this statement:
(let i = 0; i <numberArray.length; i++)
You just need to reverse the direction of your loop. Means start i with last index and then gradually decrease it to 0
function revertNumbers(...numberArray) {
let rev = [];
for(let i = numberArray.length - 1; i >= 0; i--)
{
rev.push(numberArray[i])
}
return rev.join(",")
}
console.log("revertNumbers", revertNumbers(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) === "9,8,7,6,5,4,3,2,1,0");
This is also a good use case of reduceRight()
const revertNumbers = (...arr) => arr.reduceRight((ac, a) => ([...ac, a]), []).join(',')
console.log("revertNumbers", revertNumbers(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) === "9,8,7,6,5,4,3,2,1,0");
Here is a solution that manipulates the array in place, and only has to traverse half of the original array in order to reverse it. This ekes out some modest performance gains compared to other answers in this thread (my function narrowly beats out or matches the speed of even the native reverse method in ops/sec), but micro-optimizations are largely irrelevant for this problem unless you are talking about a truly massive list of numbers.
Nonetheless, here is my answer:
const revNums = (...numArray) => {
for (
let arrLen = numArray.length,
breakPoint = ((arrLen / 2)|0) - 1,
i = arrLen,
k = 0,
temp;
--i !== breakPoint;
++k
) {
temp = numArray[i];
numArray[i] = numArray[k];
numArray[k] = temp;
}
return numArray.join(',');
};
You could reduce the original array and unshift each element onto the new array.
function revertNumbers(...numberArray) {
return numberArray.reduce((r, e) => { r.unshift(e); return r }, []).join(',')
}
console.log("revertNumbers", revertNumbers(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) === "9,8,7,6,5,4,3,2,1,0")
If you don't want to unshift, you can concat in reverse.
function revertNumbers(...numberArray) {
return numberArray.reduce((r, e, i, a) => r.concat(a[a.length - i - 1]), []).join(',')
}
console.log("revertNumbers", revertNumbers(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) === "9,8,7,6,5,4,3,2,1,0")
You could take a value and the rest of the arguments and use a recursive approach to get a reversed array of arguments.
function revertNumbers(v, ...rest) {
return rest.length
? [...revertNumbers(...rest), v]
: [v];
}
console.log(revertNumbers(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
It is to ask how many solutions can be possible ?
here are 3 of them...
"use strict";
const targetString = '9,8,7,6,5,4,3,2,1,0'
;
function soluce_1(...numberArray)
{
const rev = [];
for( let i=numberArray.length;i--;) { rev.push(numberArray[i]) }
return rev.join(',')
}
function soluce_2(...numberArray)
{
const rev = [];
let pos = numberArray.length;
for(let N in numberArray) { rev[--pos] = N }
return rev.join(",")
}
function soluce_3(...numberArray)
{
const rev = [];
while(numberArray.length) { rev.push(numberArray.pop()) }
return rev.join(',')
}
console.log('soluce_1 ->', (soluce_1(0,1,2,3,4,5,6,7,8,9)===targetString) );
console.log('soluce_2 ->', (soluce_2(0,1,2,3,4,5,6,7,8,9)===targetString) );
console.log('soluce_3 ->', (soluce_3(0,1,2,3,4,5,6,7,8,9)===targetString) );
And yes, I code in Whitesmiths style, please respect this (the reason for the downVote for correct answers ?)
https://en.wikipedia.org/wiki/Indentation_style#Whitesmiths_style
You might reverse like this:
function reverse(...a) {
const h = a.length >> 1, l = a.length-1;
for (let i = 0; i < h; ++i) [a[i], a[l-i]] = [a[l-i], a[i]];
return a;
}
console.log(reverse(0, 1, 2, 3, 4, 5, 6, 7, 8, 9).join(','));
There is a lot of Questions about if an array contains all elements of another array and they return only true or false but i need the index of where it starts,
Example:
array1 = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
array2 = [7,8,9,10,11];
It should be index = 6
Edit:I have a static or constant array with the following numbers: [2,5,10,5,5,5,8,1,4,6,2,7,6,3,8,2,4]
and i will get an array of numbers like this one: [2,8,3,8,4,2,3,2,2,4,2,8,2,6,2,5,10,5,5,5,8,1,4,6,2,7,6,2,7,6,3,8,2,4,2,3,7,3,12,3,8,2,2,6,3,2,3,2,9,2,5,2,3,5]
I need to find the sequence of numbers and the index of where it starts (in this case is 14).
I'm kind of new to programming that is why i'm asking for a simple solution with loops and if statements
I tried with something like this but it failed so bad
for (var i = 0; i < array_Input.length; i++) {
if (array_Input[i] == 2 && array_Input[i+1] == 5 && array_Input[i+2] == 10 && array_Input[i+3] == 5 && array_Input[i+4] == 5 && array_Input[i+5] == 5) {var index=+ 1;}
}
Note that i haven't tried comparing one array with the other one
Thank you all for your help
You can check if slices of array1 starting at various indices equal array2 using every:
function findIndex(a1, a2) {
for (var i = 0; i < a1.length - a2.length + 1; i++) {
if (a1.slice(i, i + a2.length).every((n, j) => n === a2[j])) return i;
}
return -1;
}
var array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
var array2 = [7, 8, 9, 10, 11];
console.log(findIndex(array1, array2));
you can check if array1 contains all values of array2 :
let array1 = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
let array2 = [7,8,9,10,11];
let minOfArray2 = Math.min(...array2);
let flag = true;
let indexWhereItStarts;
let found = false;
array2.map( val => {
if(!array1.includes(val)) flag = false;
});
array1.map( (val, index) => {
if(val === minOfArray2) indexWhereItStarts = index;
});
console.log(flag);
console.log(indexWhereItStarts);
or you can check all with two one liner (reduce method) :
let array1 = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
let array2 = [7,8,9,10,11];
let minOfArray2 = Math.min(...array2);
let flag2 = array2.reduce((acc,val) => array1.includes(val) ? acc && true : false, true);
let indexWhereItStarts2 = array1.reduce((acc, val, i) => val === minOfArray2 ? i : acc, 0);
console.log(flag2);
console.log(indexWhereItStarts2);
Im wondering about a problem I have in Javascript. I have a scenario where I need to fill gaps in an array with averages of the surrounding values. Let me give an example:
Array:
1, 2, 3, ,4, 5
In this particular case I would need to fill the gap with average of the surrounding numbers, i.e. 3.5. I think this is relatively easy to do.
However, I also need to make sure this works when there is more subsequent gaps in the array.
Example:
1, 2, 3, , , 5, 6
In this case the two gaps should be filled with the average of 3 and 5, resulting in ... 3, 4, 4, 5.
The moment I got stuck was when I tried iterating the array and filling the gaps because I filled the first gap with 4, but at that moment, the surrounding numbers for the second gap were 4 (the original gap) and 5, so I ended up with
... 3, 4, 4.5, 5, ...
which is not what I need.
Im using jQuery to iterate the array and get the values from a table.
This is how Im loading the array:
var list = [];
$('#mytable > tbody > tr').each(function() {
$this = $(this);
list.push(eval($this.find("input.number").val());
}
Now I need to iterate and fill the gaps in "list"
Here's one possible implementation:
function fill(arr) {
while (arr.includes(undefined)) {
const startIndex = arr.findIndex(num => num === undefined);
const endIndex = arr.findIndex((num, i) => i >= startIndex && num !== undefined);
const avg = (arr[startIndex - 1] + arr[endIndex]) / 2;
for (let i = startIndex; i < endIndex; i++) arr[i] = avg;
}
return arr;
}
console.log(fill([1, 2, 3, , , 5, 6]));
console.log(fill([1, , , , , , 6]));
console.log(fill([1, , , , 3, 4, , , 6]));
Try this code
var x = "1, 2, 3, ,4, 5";
var y = "1, 2, 3, , , 5, 6";
var z = "1, , , , , , 6";
var q = "1, , , , 3, 4, , , 6";
function removeSpace(str) {
return str.replace(/ /g, "");
}
function splitString(str) {
return str.split(',');
}
function fill(str) {
var z = removeSpace(str);
var zPrime = splitString(z);
for (var i = 0; i < zPrime.length; i++) {
if (zPrime[i] == "") {
if (i + 1 < zPrime.length && zPrime[i + 1] != "") {
zPrime[i] = (Number(zPrime[i - 1]) + Number(zPrime[i + 1])) / 2;
} else {
var j = i + 1;
while (j < zPrime.length && zPrime[j] == "") j++;
var tp = (j < zPrime.length) ? Number(zPrime[j]) : 0;
var dn = (i - 1 > -1) ? Number(zPrime[i - 1]) : 0;
for (var k = i; k < j; k++) {
zPrime[k] = ((tp + dn) / 2) + '';
}
}
}
}
return zPrime;
}
console.log(fill(x));
console.log(fill(y));
console.log(fill(z));
console.log(fill(q));
You can do something like this using simple iteration.
function fillMissing(arr) {
// array for storing result
var res = [];
// iterate over the array
for (i = 0; i < arr.length; i++) {
// if undefined then call the function to calculate average or set the value
res[i] = arr[i] == undefined ? calculateAverage(arr, i) : arr[i];
}
return res;
}
function calculateAverage(arr1, i) {
// set preve and next value as nearest element
var prev = arr1[i - 1],
next = arr1[i + 1],
j = 1; // variable for iterating
// iterate to find out nearest defined value
// after the element
while (prev == undefined) { prev = arr1[i - ++j]; }
j = 1; // reset for next iteration
// iterate to find out nearest defined value
// before the element
while (next == undefined) { next = arr1[i + ++j]; }
//find average and return
return (prev + next) / 2;
}
console.log(fillMissing([1, 2, 3, , , 5, 6]));
console.log(fillMissing([1, 2, 3, , , 5, 6]));
console.log(fillMissing([1, , , , , , 6]));
console.log(fillMissing([1, , , , 3, 4, , , 6]));
You could iterate the sparse array and store the last index and value. If a gap is found, the gap is filled with the average of the last value and the actual value.
function fill(array) {
array.reduce((last, v, i, a) => {
var j, avg;
if (last.index + 1 !== i) {
avg = (v + last.value) / 2;
for (j = 1; j < i - last.index; j++) {
a[last.index + j] = avg;
}
}
return { index: i, value: v };
}, { index: -1 });
return array;
}
console.log(fill([1, 2, 3, , , 5, 6]));
console.log(fill([1, , , , , , 6]));
console.log(fill([1, , , , 3, 4, , , 6]));
Interesting question that made me think a bit.
My first idea was to use map but I found that it does not consider holes. Fixed that with Array.from that converts holes to undefined
I was hoping to find a more concise solution but I'm posting it anyways
function fillMissing(a){
return Array.from(a).map((e,i)=> e !== undefined ? e : averageAround(i,a))
}
const averageAround = (index, array) => average(before(index, array), after(index, array))
const average = (a, b) => (a+b)/2
const before = findFirstNotUndefined.bind(null, -1)
const after = findFirstNotUndefined.bind(null, 1)
function findFirstNotUndefined(direction, index, array){
if (array[index] !== undefined) return array[index]
return findFirstNotUndefined(direction, index+direction, array)
}
console.log(fillMissing([1, 2, 3, , , 5, 6]));
Some thoughts:
recursive call to findFirstNotUndefined is in tail call position
findFirstNotUndefined should be memoizable, (maybe) useful for large holes
average around can be written point free style but not without adding another function or importing some fp library like ramda
Modifying the signature of averageAround like (_, index, array), it can be used directly in the map: Array.from(a).map(averageAround). Cool to read even if it computes the average on every value ((val + val)/2)
There is a recursive way to do this, Basically it counts the empty spots between two values and divides the difference over these empty spots:
var arr = [1, , , , 3, 4, , , 6];
for( var i = 0; i < arr.length; i++ ){
if( arr[ i ] === undefined )
arr[ i ] = avg( arr[ i - 1 ], arr.slice( i + 1, arr.length ), 1 );
}
function avg( low, arr, recursion ){
if( arr[ 0 ] === undefined )
return avg( low, arr.slice( 1, arr.length ), recursion + 1 );
return low + ( ( arr[0] - low ) / ( recursion + 1 ) );
}
console.log( arr );
Works like a charm:
arr = [1, 2, 3, ,4, 5] => [1, 2, 3, 3.5, 4, 5]
arr = [1, 2, 3, , , 5, 6] => [1, 2, 3, 3.6665, 4.3333, 5, 6]
arr = [1, , , , 3, 4, , , 6] => [1, 1.5, 2, 2.5, 3, 4, 4.6667, 5.3334, 6]
Another functional recursive version
const arr = [1,2,3,,,5,6]
function fill([head,...tail], lastNotNull, holeWidth = 0){
if (tail.length === 0 ) return head
if (head === undefined) return fill(tail, lastNotNull, ++holeWidth)
return Array(holeWidth).fill((lastNotNull+head)/2).concat(head).concat(fill(tail, head))
}
console.log(fill(arr))
Explanation:
First parameter of fill function is destructured into head and tail. Head represent the current value and tail next values
Base case: tail empty -> we just return head
If current value head is undefined, we recurse increasing the size of the hole and keeping the last not null value, to compute the average
In all other cases we fill the hole with the average, we add the current value and then recurse onto remaining array, resetting lastNotNull to head and holeWidth to 0 with default value
I feel that the last step could be optimized in terms of execution time but I like the fact that it's compact and clear (if already comfortable with recursion)
Bonus: I love the fact that the hole is filled with the Array.prototype.fill function
I have an array:
var myArray = [2, 4, 6];
and another array:
var otherArray = [1, , 3, , 5, , 7];
I'm trying to map (or use any non "for/for-each" iterator) to place each myArray value into the corresponding empty spaces of otherArray.
Hopeful output:
newArray = [1, 2, 3, 4, 5, 6, 7];
Any ideas?
otherArray.forEach(function (val, idx) {
if (typeof val === 'undefined') {
otherArray[idx] = myArray.shift();
}
});
forEach may not be compatible if supporting IE < 9 though.
Using Array.prototype.map:
var newArray = otherArray.map(function(val) {
return typeof val === 'undefined' ? myArray.shift() : val;
});
Be aware that this will not hit indexes that have never been set.
Using while loop:
while (myArray.length > 0) {
var emptyIdx = otherArray.indexOf();
otherArray[emptyIdx] = myArray.shift();
}
Edit: Ok, if the elements in the array are truly not set, as they are in your description, these solutions won't work since they'll skip over the unset indexes. Here's one that would work:
var myArray = [2, 4, 6, 8, 9];
var otherArray = [1, , 3, , 5, , 7];
var lastIdx = -1;
otherArray.forEach(function(val, idx) {
if (idx - lastIdx > 1) {
otherArray[idx - 1] = myArray.shift();
}
});
if (myArray.length > 0) {
otherArray = otherArray.concat(myArray);
}
document.body.innerHTML = otherArray;
You can iterate through the array and check for undefined values like:
var otherArray = [1, , 3, , 5, , 7];
var myArray = [2, 4, 6];
for (var i = 0, j = 0; i < otherArray.length; i++) {
//check if a value is undefined
if (!otherArray[i]) {
//then change this value with the new from other array
otherArray[i] = myArray[j];
j++;
}
}
console.log(otherArray);//prints [1, 2, 3, 4, 5, 6, 7]
You could use recursivity, this function will fill the undefined items of the first array with the items of the second one until it reach the end of one of the arrays used.
var otherArray = [1, , 3, , 5, , 7];
var myArray = [2, 4, 6];
function fillArray(ar1, ar2, i){
if (!i) i = 0;
if (!ar1[i]){
ar1[i] = ar2.shift();
}
if (++i < ar1.length && ar2.length > 0){
fillArray(ar1, ar2, i);
}
}
fillArray(otherArray, myArray); // this will update the content of originals arrays,
// use otherArray.slice() to get a copy.
document.getElementById("result").innerHTML = JSON.stringify(otherArray);
<div id="result"></div>
If you want to add elements (because there is other items in myArray and there is no space left in otherArray) you can change the condition to continue replacing the && with ||
if (++i < ar1.length || ar2.length > 0){