Alternative to array.splice in JavaScript - javascript

I am currently working on a project where I store numeric values in a JS array. After some changes it should be removed again. I currently use the array.splice method like this:
function removeA(arr, element) {
var index = arr.indexOf(element);
if (index >= 0) {
arr.splice(index, 1 );
}
return arr;
}
But this seems to give me issues on Safari. This piece of code works in every browser, like Chrome, Firefox, Opera. But not on Safari. It even works in the Technical Preview of Safari.
Does anyone have an alternative?
Thanks in advance :)

You have to slice before and after the index, and concat the results. Note that Array.prototype.slice() doesn't mutate the original array like Array.prototype.splice() does.
var arr = [0, 1, 2, 3, 4, 5, 6, 7];
var index = 5;
var result = arr.slice(0, index).concat(arr.slice(index + 1));
console.log(result);
Or using ES6 and array spread:
var arr = [0, 1, 2, 3, 4, 5, 6, 7];
var index = 5;
var result = [...arr.slice(0, index), ...arr.slice(index + 1)];
console.log(result);

You can use the built-in filter()
var array = [1,2,3,7,4,5,6,7,12,54,7,691];
var array = array.filter(x => x !== 7);
console.log(array);

Another Alternative to array.splice in JavaScript is array.reduce
var arr =[1,2,3,2,4,5,6,2];
var newarr = arr.reduce((acc, elem) => elem !== 2 ? acc.concat(elem) : acc, []);
console.log(newarr);

Try the slice() method
arr = arr.slice(index, 1 );

Sorry for late but hopefully it is useful for someone else
var arr = [32, 33, 16, 40, 55, 2, 41, 3, 10];
document.write("Array : "+arr);
document.write("<br>");
document.write("Removed Elements : "+mySplice(arr,2,2));
document.write("<br>");
document.write("Processed Array : "+arr);
function mySplice(array,index,count) {
var fixIndex = -1;
var ret = [];
arr = array.filter(function(element) {
fixIndex++;
if((fixIndex >= index && fixIndex < (index+count))) {
ret[ret.length]=element;
return false;
} else {
return true;
}
});
return ret;
}
Or you can use simple version (NOTE: it is simple but reversed)
var arr = [32, 33, 16, 40, 55, 2, 41, 3, 10];
document.write("Array : "+arr);
document.write("<br>");
document.write("Processed Array : "+mySplice_simple(arr,2,2));
function mySplice_simple(arr,index,count) {
fixIndex = -1;
return arr.filter(function(i) {
fixIndex++;
return !(fixIndex >= index && fixIndex < (index+count));
});
}
Or if you have to remove just one element then use this
var arr = [32, 33, 16, 40, 55, 2, 41, 3, 10];
document.write("Array : "+arr);
document.write("<br>");
document.write("Processed Array : "+mySplice_simple_v2(arr,2));
function mySplice_simple_v2(arr,index,count) {
fixIndex = -1;
return arr.filter(function(i) {
fixIndex++;
return fixIndex != index;
});
}

Some more ideas:
Option A flatMap():
Return an empty [] in order to "filter" elements. Less efficient but might be useful in case you want to add new elements as well.
const a = [3, 4, 5, 6];
const filter = 2;
const r = a.flatMap((v, j) => j !== filter ? v : []);
console.log(`Result: %o`, r); // Result: [3, 4, 6]
Example for filter + insert
const a = [3, 4, 5, 6];
const filter = 2;
const insert = 1;
const value = 4.5;
const r = a.flatMap((v, j) => {
if (j === filter) return [];
if (j === insert) return [v, value];
return v;
});
console.log(`Result: %o`, r); // Result: [3, 4, 4.5, 6]
Option B Array.from():
const a = [3, 4, 5, 6];
const filter = 2;
const r = Array.from({length: a.length -1}, (_, i) => a[i >= filter ? i + 1: i]);
console.log(`Result: %o`, r); // Result: [3, 4, 6]
Option C "Destructure":
const a = [3, 4, 5, 6];
const filter = 2;
const {[filter]: _, ...o} = a;
const r = Object.values(o);
console.log(`Result: %o`, r); // Result: [3, 4, 6]

Related

issue with merge sorted arrays problem using javascript

I am trying to solve merge 2 sorted arrays problem using javascript. Please find my solution below:
input:
const arr1 = [1, 4, 7, 8, 10];
const arr2 = [2, 3, 9];
output:
[1, 2, 3, 4, 7, 8, 9 10]
const arr1 = [1, 4, 7, 8, 10];
const arr2 = [2, 3, 9];
let arrayItem1 = arr1[0];
let arrayItem2 = arr2[0];
let i = 1;
let j = 1;
let mergedArray = [];
while(arrayItem2 || arrayItem1) {
arrayItem1 = arrayItem1 === undefined ? 0 : arrayItem1;
arrayItem2 = arrayItem2 === undefined ? 0 : arrayItem2;
if (arrayItem1 < arrayItem2) {
console.log('inside if');
console.log("first array", arrayItem1);
arrayItem1 = arr1[i];
i++;
mergedArray.push(arrayItem1);
} else {
console.log('inside else');
console.log("second array", arrayItem2);
arrayItem2 = arr2[j];
j++;
mergedArray.push(arrayItem2);
}
console.log("== merged array ==", mergedArray);
}
But it is going in infinite loop. Not sure where I am going wrong. Need a watchful pair of eyes here.
thanks
You need to check the index with the lengths of the arrays and add a final check for getting the rest of the arrays added to the merged array.
const
array1 = [1, 4, 7, 8, 10],
array2 = [2, 3, 9],
mergedArray = [];
let i = 0,
j = 0;
while (i < array1.length && j < array2.length) {
if (array1[i] < array2[j]) {
mergedArray.push(array1[i++]);
} else {
mergedArray.push(array2[j++]);
}
}
if (i < array1.length) mergedArray.push(...array1.slice(i));
if (j < array2.length) mergedArray.push(...array2.slice(j));
console.log(...mergedArray);
const arr1 = [1, 4, 7, 8, 10];
const arr2 = [2, 3, 9];
const mergedArrays = [...arr1, ...arr2];
// WITH SORT
const result = mergedArrays.sort((a, b) => Number(a) - Number(b));
console.log(result);
// WITHOUT SORT
const bubbleSort = (arr) => {
let done = false;
while (!done) {
done = true;
arr.forEach((el, i) => {
if (arr[i - 1] > arr[i]) {
done = false;
const tmp = arr[i - 1];
arr[i - 1] = arr[i];
arr[i] = tmp;
}
});
}
return arr;
};
const result2 = bubbleSort(mergedArrays)
console.log(result2)
You don't really need to go through all that trouble, you can merge your arrays by destructuring your arrays in new one and just use the Array.sort() method.
UPDATE:
Added sorting without using using Array.sort(), using a sorting algorithm Bubble sort
This will also work for non positive numbers
//[1, 2, 3, 4, 7, 8, 9 10]
const arr1 = [1, 4, 7, 8, 10];
const arr2 = [2, 3, 9];
let arrayItem1 = arr1[0];
let arrayItem2 = arr2[0];
let i = 1;
let j = 1;
let mergedArray = [];
while(arrayItem2 !== undefined || arrayItem1 !== undefined) {
if (arrayItem2 === undefined || arrayItem1 < arrayItem2) {
mergedArray.push(arrayItem1);
arrayItem1 = arr1[i];
i++;
} else {
mergedArray.push(arrayItem2);
arrayItem2 = arr2[j];
j++;
}
console.log('Merged array: ' + mergedArray)
}
Some issues:
The actions in the if block (and else block) occur in the wrong order. You first want to push the item, then increment the index, and then get the next value from the array so it will be used in the next comparison.
Don't assign the value 0 when a value is undefined. Just leave it undefined, otherwise you risk to push a 0 into the result that was never there in the input.
So:
const arr1 = [1, 4, 7, 8, 10];
const arr2 = [2, 3, 9];
let arrayItem1 = arr1[0];
let arrayItem2 = arr2[0];
let i = 1;
let j = 1;
let mergedArray = [];
while(arrayItem2 || arrayItem1) {
if (arrayItem2 === undefined || arrayItem1 < arrayItem2) {
mergedArray.push(arrayItem1);
i++;
arrayItem1 = arr1[i];
} else {
mergedArray.push(arrayItem2);
j++;
arrayItem2 = arr2[j];
}
}
console.log("== merged array ==", mergedArray);
const arr1 = [1, 4, 7, 8, 10];
const arr2 = [2, 3, 9];
var children = arr1.concat(arr2);
console.log (children.sort(function(a, b){return a - b}));
children.sort(function(a, b){return a - b});
const arr1 = [1, 4, 7, 8, 10];
const arr2 = [2, 3, 9];
var children = arr1.concat(arr2);
console.log (children.sort(function(a, b){return a - b}));

Remove Only One Duplicate from An Array

I'm trying to only remove one of the 2s from an array, but my code removes all of them. My code is as follows:
var arr = [2,7,9,5,2]
arr.filter(item => ((item !== 2)));
and:
var arr = [2,7,9,2,2,5,2]
arr.filter(item => ((item !== 2)));
Both remove all the 2s. I thought about removing duplicates, where it works if there's only one duplicate - e.g.:
Array.from(new Set([2,7,9,5,2]));
function uniq(a) {
return Array.from(new Set(a))
}
But fails if there's multiple duplicates as it just removes them all, including any other duplicated numbers:
Array.from(new Set([2,7,9,9,2,2,5,2]));
function uniq(a) {
return Array.from(new Set(a))
}
Does anyone know how to only remove one of the 2s? Thanks for any help here.
You could use indexOf method in combination with splice.
var arr = [2,7,9,5,2]
var idx = arr.indexOf(2)
if (idx >= 0) {
arr.splice(idx, 1);
}
console.log(arr);
You could take a closure with a counter and remove only the first 2.
var array = [2, 7, 9, 2, 3, 2, 5, 2],
result = array.filter((i => v => v !== 2 || --i)(1));
console.log(result);
For any other 2, you could adjust the start value for decrementing.
var array = [2, 7, 9, 2, 3, 2, 5, 2],
result = array.filter((i => v => v !== 2 || --i)(2));
console.log(result);
There are various ways to do that; one relatively simple way would be to use indexOf; see this other post: https://stackoverflow.com/a/5767357/679240
var array = [2, 7, 9, 5, 2];
console.log(array)
var index = array.indexOf(2);
if (index > -1) {
array.splice(index, 1);
}
// array = [7, 9, 5, 2]
console.log(array);
you can follow the following method
var arr= [2,3,4,2,4,5];
var unique = [];
$.each(arr, function(i, el){
if($.inArray(el, unique) === -1) unique.push(el);
})
You can do:
const arr = [2, 7, 9, 2, 2, 5, 2];
const result = arr
.reduce((a, c) => {
a.temp[c] = ++a.temp[c] || 1;
if (a.temp[c] !== 2) {
a.array.push(c);
}
return a;
}, {temp: {}, array: []})
.array;
console.log(result);
Most simple way to filter all duplicates from array:
arr.filter((item, position) => arr.indexOf(item) === position)
This method skip element if another element with the same value already exist.
If you need to filter only first duplicate, you can use additional bool key:
arr.filter((item, position) => {
if (!already && arr.indexOf(item) !== position) {
already = true
return false
} else return true
})
But this method have overheaded. Smartest way is use for loop:
for (let i = 0; i < arr.length; i++) {
if (arr.indexOf(arr[i]) !== i) {
arr.splice(i,1);
break;
}
}

JS - Sum Of Two Arrays where arrays can be of unequal length

I need function like this.
function sum(arr1, arr2) {
return totalArray
};
sum([1,2,3,4], [5,6,7,8,9]) // [6,8,10,12,9]
I tried it this way:
var array1 = [1, 2, 3, 4];
var array2 = [5, 6, 7, 8, 100];
var sum = array1.map((num, idx) => num + array2[idx]); // [6,8,10,12]
First you can get an array out of the function's arguments using Spread syntax (...), then sort it by array's length using Array.prototype.sort() and finally Array.prototype.reduce() to get the result array
Code:
const sum =(...arrays) => arrays
.sort((a, b) => b.length - a.length)
.reduce((a, c) => a.map((n, i) => n + (c[i] || 0)) || c)
// two arrays
const resultTwoArrays = sum([1, 2, 3, 4], [5, 6, 7, 8, 9])
console.log(resultTwoArrays) // [6, 8, 10, 12, 9]
// three arrays or more...
const resultThreeArrays = sum([1, 2, 3, 4], [5, 6, 7, 8, 9], [1, 2])
console.log(resultThreeArrays) // [7, 10, 10, 12, 9]
.as-console-wrapper { max-height: 100% !important; top: 0; }
At the risk of being unpopular due to using a loop:
function sum(arr1, arr2) {
let totalArray = [];
const totalLength = Math.max(arr1.length, arr2.length);
for (let i = 0; i < totalLength; i++) {
totalArray[i] = (arr1[i] || 0) + (arr2[i] || 0);
}
return totalArray;
}
The || 0 handles the possibility the array doesn't have an entry at i, because if it doesn't, the result of arrX[i] is undefined, and undefined || 0 is 0.
I try this way.
var array1 = [1, 2, 3, 4];
var array2 = [5, 6, 7, 8, 100];
var sum = array1.map((num, idx) => num + array2[idx]); // [6,8,10,12]
Very close, but map will stop at the end of array1, so you won't get the subsequent entries from array2. Just pick the longer of the two arrays, then handle the fact that the other array may not have an entry at arrayX[idx]. You can do that with the || 0 idiom:
function sum(array1, array2) {
var a, b;
if (array1.length > array2.length) {
a = array1;
b = array2;
} else {
a = array2;
b = array1;
}
return a.map((num, idx) => num + (b[idx] || 0));
}
console.log(sum([1, 2, 3, 4], [5, 6, 7, 8, 100]));
Alternately, you can use the new (but polyfill-able) Array.from to create the result array and use the callback to build the entries:
function sum(array1, array2) {
return Array.from(
{length: Math.max(array1.length, array2.length)},
(_, i) => (array1[i] || 0) + (array2[i] || 0)
);
}
console.log(sum([1, 2, 3, 4], [5, 6, 7, 8, 100]));
Mosho's answer is wonderfully simple, though.
Find the long and short array according to length. Iterate the short array with Array.map(), and take the value from the long array. Then add the leftovers from the long array using Array.slice(), and Array.concat():
function sum(arr1, arr2) {
const [l, s] = arr1.length >= arr2.length ? [arr1, arr2] : [arr2, arr1];
return s.map((n, i) => n + l[i])
.concat(l.slice(s.length));
};
console.log(sum([1,2,3,4], [5,6,7,8,9]));
Are we code golfing this? Here's a generator solution.
const summer = function*(a, b, i=0) {
while(i < a.length || i < b.length) yield (a[i] || 0) + (b[i++] || 0);
};
const sum = (a, b) => [...summer(a,b)];
console.log(sum([1,2,3,4], [5,6,7,8,9])) // [6,8,10,12,9]
You can have a custom logic something like this:
function sum(arr1, arr2) {
var length, selectedArray, nonSelectedArray;
if(arr1.length>arr2.length){
length = arr1.length;
selectedArray = arr2;
nonSelectedArray = arr1;
}else {
length = arr2.length;
selectedArray = arr1;
nonSelectedArray = arr2;
}
var totalArray = [];
for(var i=0; i<length; i++){
if(selectedArray[i]){
totalArray.push(selectedArray[i] + nonSelectedArray[i]);
} else {
totalArray.push(nonSelectedArray[i]);
}
}
return totalArray
};
var res = sum([1,2,3,4], [5,6,7,8,9]);
console.log(res);
Try with map():
function sum(arr1, arr2) {
var [a1, a2] = arr1.length > arr2.length ? [arr1, arr2] : [arr2, arr1]
var totalArray = a1.map(function(i, idx){
i = (i + a2[idx] || i + 0);
return i;
})
return totalArray;
};
console.log(sum([1,2,3,4], [5,6,7,8,9])) // [6,8,10,12,9]

Get Indexes of Filtered Array Items

In JavaScript, I have the following array
var arr = [5, 10, 2, 7];
From that array, I would like to get an array containing only the indexes of the items that are less than 10. So, in the above example, the indexes array would be
var indexes = [0, 2, 3];
Now, I want something simlar to filter, but that would return the indexes.
If I try filter, this is how it will work
var newArr = arr.filter(function (d) {
return (d < 10);
});
// newArr will be: [5, 2, 7];
This is not what I want. I want something along the following lines (note this is a pseudo-code)
var indexes = arr.filter(function (d) {
/* SOMETHING ALONG THE FOLLOWING PSEUDOCODE */
/* return Index of filter (d < 10); */
});
// indexes will be: [0, 2, 3];
How can I do that? Thanks.
Use a reducer.
var arr = [5, 10, 2, 7];
var newArr = arr.reduce(function(acc, curr, index) {
if (curr < 10) {
acc.push(index);
}
return acc;
}, []);
console.log(newArr);
You can use a forEach loop:
const arr = [5, 10, 2, 7];
const customFilter = (arr, min) => {
const result = [];
arr.forEach((element, index) => {
if (element < min) {
result.push(index);
}
});
return result;
}
console.log(customFilter(arr, 10));
You can use array#reduce and add indexes whose value is greater than 10.
var arr = [5, 10, 2, 7];
var indexes = arr.reduce((r, d, i) => d < 10 ? (r.push(i), r) : r , []);
console.log(indexes);

Make nested array to group array elements

I have array:
arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14];
Then I want to make group of 4 elements.
Every iteration, this array must be modified until it get's final face.
Step 1:
arr = [[1,2,3,4],5,6,7,8,9,10,11,12,13,14];
Step 2:
arr = [[1,2,3,4],[5,6,7,8],9,10,11,12,13,14];
Step 3:
arr = [[1,2,3,4],[5,6,7,8],[9,10,11,12],13,14];
Step 3:
arr = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14]];
How is this possible?
I tried this:
var array = [1,2,3,4,5,6,7,8,9,10,11,12,13,14]
var i,j,temparray,chunk = 4;
for (i=0,j=array.length; i<j; i+=chunk) {
temparray = array.slice(i,i+chunk);
console.log(temparray);
}
But I don't know then how to save this chunk into own array and not in the new array.
Using Array#reduce method.
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
newArr = arr.reduce((acc, item, index) => {
if ((index) % 4 === 0) {
acc.push([item]);
} else {
acc[acc.length - 1].push(item);
}
return acc;
}, []);
console.log(newArr); // [ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9, 10, 11, 12 ], [ 13, 14 ] ]
You could splice the array until the length is smaller than the index of the last insertation.
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
i = 0;
while (i < array.length) {
array.splice(i, 0, array.splice(i, 4));
console.log(JSON.stringify(array));
i++;
}
lodash probably has better performances than my implementation, but if you are looking to do so with vanilla javascript then you can like this (though many other ways are possible):
var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14];
var newArr = arr.reduce((acc, val, idx)=>{
if(idx % 4 === 0){
acc.push([]);
}
acc[acc.length-1].push(val)
return acc
}, [])
console.log(newArr);
The lodash method chunk will do this for you.
result = _.chunk(arr, 4);
function chunkArray(myArray, chunk_size){
var index = 0;
var arrayLength = myArray.length;
var tempArray = [];
for (index = 0; index < arrayLength; index += chunk_size) {
myChunk = myArray.slice(index, index+chunk_size);
// Do something if you want with the group
tempArray.push(myChunk);
}
return tempArray;
}
// Split in group of 3 items
var result = chunkArray([1,2,3,4,5,6,7,8], 3);
// Outputs : [ [1,2,3] , [4,5,6] ,[7,8] ]
console.log(result);
Just push it to the resulting array:
const chunk = 4, result = []
for (var i = 0, j = array.length; i < j; i += chunk) {
result.push(array.slice(i,i + chunk));
}
I thought it would be fun too if I add one more solution using recursive calls, Happy coding!
Test it here
function split(arr, offset, res){
//stop condition (offset exceeds len of array)
if(offset>arr.length)
return res;
//slice 4 elms
res.push(arr.slice(offset,offset+4));
//recursion
return split(arr, offset+4, res);
}
var res = split([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], 0, []);
console.log(res);

Categories

Resources