I have an array arr:
arr = [0,1,2,3,4,5]
How can I reorder/ shift multiple elements? For example,
I want to remove 0,2 and 3 and put them at index 4 so that the final array should be [1,0,2,3,4,5]
In the above example, index 4 is with the perspective of the original array, not the final array.
I tried using splice like this:
items = [0,2,3] // items to be reordered
indexes = [0,2,3] // get their indexes
arr = [...arr.filter((it)=> !indexes.includes(arr.indexOf(it)))]
arr.splice(4, 0, ...items)
// result [1, 4, 5, 0, 2, 3]
The above is not the intended result
This solution mutates the array.
You could store the value at the inser position and remove the items and splice the removed items after the index of the stored item.
position v
index 0 1 2 3 4
array [0, 1, 2, 3, 4, 5] store value at index
1 4 5 rest array after removing items
1 4 [0 2 3] 5 splice with removed items
var array = [0, 1, 2, 3, 4, 5],
remove = [0, 2, 3],
insertAtIndex = 4,
valueAtPosition = array[insertAtIndex];
remove.forEach(v => array.splice(array.indexOf(v), 1));
array.splice(array.indexOf(valueAtPosition) + 1, 0, ...remove);
console.log(...array);
You can first remove the given elements and then use splice() to add them at the required index.
function shiftElementsTo(arr, inds, final){
let set = new Set(inds);
let removed = inds.map(x => arr[x]);
arr = arr.filter((x, i) => !set.has(i));
arr.splice(final, 0, ...removed);
return arr;
}
console.log(shiftElementsTo([0, 1, 2, 3, 4, 5], [0, 2, 3], 2))
Try to use this approach:
let arr = [0,1,2,3,4,5];
let rmv = [0, 2, 3];
const remove = (src, rem, i ) => {
const arrWithIndexes = src.map((a, i) => { return {value: a, index: i}});
const filtered = arrWithIndexes.filter(f => !rem.some(s=> s === f.value));
const indexToInsert = filtered.findIndex(f=>f.index === i);
const result = filtered.map(f=> f.value);
result.splice(indexToInsert, 0, ...rem);
console.log(result);
}
console.log(remove(arr, rmv, 4));
Or if you know the desired index:
let arr = [0,1,2,3,4,5];
let rmv = [0, 2, 3];
const remove = (src, rem ) => {
const filtered = src.filter(f=> !rem.some(s=> s === f));
filtered.splice(2, 0, ...rmv)
console.log(filtered);
}
console.log(remove(arr, rmv));
const temp = [0, 2, 3];
const arr = [0, 1, 2, 3, 4, 5];
const index = arr[4];
// Accepts an array (temp) and returns a function to be used
// as the callback for `filter` which accepts an element
// and returns whether that element is in the temp array
const filterUsing = (arr) => (el) => !arr.includes(el);
// `filter` the elements from the main array
const filtered = arr.filter(filterUsing(temp));
// Find the new position of the element in `index`
const newIndex = filtered.findIndex(el => el === index);
// Splice in the temp array back into the filtered array
filtered.splice(newIndex, 0, ...temp);
console.log(filtered);
Related
I have an array which one including below values:
tomb = [4, 6, 1, 3, 5, 0, 2]
tomb[0] = 4
tomb[1] = 6
tomb[2] = 1
tomb[3] = 3
tomb[4] = 5
tomb[5] = 0
tomb[6] = 2
Can I ask is possible to convert like this:
tomb[5] = 0
tomb[2] = 1
tomb[6] = 2
tomb[3] = 3
tomb[0] = 4
tomb[4] = 5
tomb[1] = 6
I would like to use in for loop this array values, but before I have to start from the minimum and increase to the biggest one. So I would like get a array index list from minimum to maximum.
const arr = [4, 6, 1, 3, 5, 0, 2];
const min = Math.min.apply(null, arr);
const index = arr.indexOf(min);
console.log(index);
You could get the keys of the array and sort the indices by the values of the given array.
const
array = [4, 6, 1, 3, 5, 0, 2],
indices = [...array.keys()].sort((a, b) => array[a] - array[b]);
console.log(...indices);
Try this one by using array.sort and array.indexOf
const arr = [4, 6, 1, 3, 5, 0, 2];
const newarr = arr.slice()
const arrindex = []
newarr.sort()
newarr.forEach(i=>{
arrindex.push(arr.indexOf(i))
})
console.log(arrindex)
Just use Array.sort()
const arr = [4, 6, 1, 3, 5, 0, 2];
const sorted = arr
.map((value, index) => ({ index, value }))
.sort((a, b) => a.value - b.value)
console.log(
sorted.map(entry => entry.index),
sorted.map(entry => entry.value)
)
Let's say I have two arrays, where array1 is always changing:
First case:
array1 = [1, 2, 3, 4, 5]
array2 = [1, 2, 3]
How can I compare them and add 4 and 5 into array2?
I am getting the difference between them doing:
let difference = array1.filter(x => !array2.includes(x));
and then doing array2.push(difference), so array2 is now equal to array1, right?
Second case:
array1 = [1, 2, 8, 9]
array2 = [1, 2, 3]
So now I need to remove 3 from array2, and add 8 and 9, how can I do this?
EDIT: I need this because I'm getting array1 from a server(they are chats) and it's dynamically changing every 5 sec, and this is problem. I need to keep the elements I already have so they won't "update" and only change the one getting deleted or added. Hope this makes sense.
First case will not work as aspectedlooking at the code,
to achive what you want you have to write:
difference.forEach((x) => array2.push(x));
instead of:
array2.push(difference)
for the second one if you want to remove a record in array2 because is missing in array1 you need to control each value of array2 in array1 and remove if not exists by ID
var array1 = [1, 2, 8, 9];
var array2 = [1, 2, 3];
//here i build difference2 collecting the value of array2 that miss on array1
let difference2 = array2.filter((x) => !array1.includes(x));
//here with splice and indexOf i remove every value collected before
difference2.forEach((x) => array2.splice(array2.indexOf(x), 1));
//following code is to add the 8 and 9
let difference = array1.filter((x) => !array2.includes(x));
difference.forEach((x) => array2.push(x));
console.log(array2);
//the result [1,2,8,9]
let array1 = [1, 2, 3, 4, 5];
let array2 = [1, 2, 3];
let filteredArray = array2.filter((a) => array1.includes(a));
let secFilteredArray = array1.filter((a) => !filteredArray.includes(a));
console.log(filteredArray.concat(secFilteredArray));
You could take a Set and delete seen items and add the rest to the array.
const
array1 = [1, 2, 8, 9],
array2 = [1, 2, 3],
set1 = new Set(array1);
let i = array2.length;
while (i--) if (!set1.delete(array2[i])) array2.splice(i, 1);
array2.push(...set1);
console.log(array2);
Just use another filter and combine the two arrays.
const array1 = [1, 2, 8, 9];
let array2 = [1, 2, 3];
const inArrOne = array1.filter(x => !array2.includes(x));
const inBothArr = array2.filter(x => array1.includes(x));
array2 = [...inBothArr, ...inArrOne];
console.log(array2);
I would avoid much built-in or third party compare functions since I am not sure what I am dealing with. This could be refactored and optimized more if the array1 is guaranteed to have an ordered list.
let localArray = [1, 2, 3, 4, 5],
lastServerArray = [];
/**
* Compares "fromArr" to "targetArr"
* #param fromArr Array of elements
* #param targetArr Array of elements
* #returns List of elements from "fromArr" that do not happen in "targetArr"
*/
const compArr = (fromArr, targetArr) => {
const result = [];
for (let i = 0, len = fromArr.length; i < len; i++) {
const elem = fromArr[i],
targetIdx = targetArr.indexOf(elem);
if (!~targetIdx && !~result.indexOf(elem)) {
// Element do not exist in "targetArr" and in current "result"
result.push(elem);
}
}
return result;
}
const updateLocalArray = (serverArray = []) => {
if (JSON.stringify(lastServerArray) === JSON.stringify(serverArray)) {
console.log('Nothing changed from server, skip updating local array');
return localArray;
}
lastServerArray = serverArray;
const notExistentLocalElems = compArr(serverArray, localArray), // Elements that do not exists in local array
notExistentServerElems = compArr(localArray, serverArray); // Elements that do not exists in server array
// Do something to those "notExistentLocalElems" or "notExistentServerElems"
// ---
// Sync server array to local array
// Remove elements that is not on server.
localArray = localArray.filter(elem => !~notExistentServerElems.indexOf(elem));
console.log('These elements removed from localArray', notExistentServerElems);
// Append elements that is on server.
localArray.push(...notExistentLocalElems);
console.log( 'These elements added into localArray', notExistentLocalElems);
return localArray;
}
updateLocalArray([1, 2, 3]);
console.log(`1. server sends [1, 2, 3] -- local becomes`, localArray);
updateLocalArray([3, 4, 5, 6]);
console.log(`2. server sends [3, 4, 5, 6] -- local becomes`, localArray);
updateLocalArray([5, 5, 4, 2, 7]);
console.log(`3. server sends [5, 5, 4, 2, 7] -- local becomes`, localArray);
updateLocalArray([0, 0, 1, 2]);
console.log(`4. server sends [0, 0, 1, 2] -- local becomes`, localArray);
You could do like this if you want to mutate array2:
let array1 = [1, 2, 8, 9];
let array2 = [1, 2, 3];
let valuesToAdd = array1.filter(x => !array2.includes(x));
let indexesToDelete = Object.entries(array2).filter(([, x]) => !array1.includes(x)).map(([i]) => i);
// Reverse iteration to preserve indexes while removing items
indexesToDelete.reverse().forEach(i => array2.splice(indexesToDelete[i], 1));
array2.push(...valuesToAdd);
console.log(array2);
function removeListedValues(arr) {
var what, a = arguments, L = a.length, ax;
while (L > 1 && arr.length) {
what = a[--L];
while ((ax= arr.indexOf(what)) !== -1) {
arr.splice(ax, 1);
}
}
return arr;
}
arr: The given array
without: A list of elements which are to be removed from arr.
Return the array after removing the listed values.
Input:
arr: [1, 2, 2, 3, 1, 2]
without: [2, 3]
Output:
[1, 1]
To remove something in array, suggest using .filter
const input = [1, 2, 2, 3, 1, 2];
const without = [2, 3];
const result = input.filter(value => !without.includes(value))
console.log(result)
You can create a Set (for faster lookup) from the array of values to exclude and use Array#filter along with Set#has.
const arr = [1, 2, 2, 3, 1, 2], without = new Set([2, 3]);
const res = arr.filter(x => !without.has(x));
console.log(res);
How to sort randomly placed values in one array so that it matches the order provided by another array, but instead of appending the duplicates one after the other, the function should append the group of values, provided by the order variable, one after the other.
Input:
const array = [1, 5, 4, 3, 5, 3, 1, 5, 4];
const order = [5, 1, 3, 4];
Correct Output:
const correctlyOrderedArray = [5, 1, 3, 4, 5, 1, 3, 4, 5];
Wrong Output:
const wronglyOrderedArray = [5, 5, 5, 1, 1, 3, 3, 4, 4];
Two functions. The first one does the actual sorting and uses the second one inside itself.
Primary function:
function sortByOrder (array, order) {
const arrayOfArrays = order.map(v => {
return [...Array(howMany(v, array))].map(undef => v);
});
const tempArray = [];
arrayOfArrays.forEach((subArr, i) => {
let index = order.indexOf(order[i]);
subArr.forEach(duplicate => {
tempArray[index] = duplicate;
index += order.length;
});
});
return tempArray.filter(v => v);
}
Subordinate function:
function howMany(value, array) {
const regExp = new RegExp(value, 'g');
return (array.join(' ').match(regExp) || []).length;
}
If we suppose that the array order contains all the non duplicated elements of the array array, one way to achieve the sorting could be to copy the element of order using a modulo so that, we can restart the copy from the beginning.
const array = [1, 5, 4, 3, 5, 3, 1, 5, 4];
const order = [5, 1, 3, 4];
var newValue = []
for(var i = 0; i < array.length; i++){
newValue.push(order[i % order.length])
}
console.log(newValue)
We could iterate over the order and shift out elements out of our array until its empty:
const array = [1, 5, 4, 3, 5, 3, 1, 5, 4];
const order = [5, 1, 3, 4];
let i = 0, exit = false;
const result = [];
while(array.length){
const found = array.findIndex(el => el === order[i % order.length]);
if(found+1){
result.push( array.splice(found, 1)[0] );
exit = false;
}
if(i && i % order.length){
if(exit){
result.push(...array); //concat the rest
break;
}
exit = true;
}
i++;
}
The exit boolean will terminate the program if one order iteration did not found anything, e.g.:
const order = [1,2,3], array = [4,5,6,1,2,3,1,2,3];
Let it run!
If i have an array A = [1, 4, 3, 2] and B = [0, 2, 1, 2] I want to return a new array (A - B) with values [1, 2, 2, 0]. What is the most efficient approach to do this in javascript?
const A = [1, 4, 3, 2]
const B = [0, 2, 1, 2]
console.log(A.filter(n => !B.includes(n)))
Use map method
The map method takes three parameters in it's callback function like below
currentValue, index, array
var a = [1, 4, 3, 2],
b = [0, 2, 1, 2]
var x = a.map(function(item, index) {
// In this case item correspond to currentValue of array a,
// using index to get value from array b
return item - b[index];
})
console.log(x);
For Simple and efficient ever.
Check here : JsPref - For Vs Map Vs forEach
var a = [1, 4, 3, 2],
b = [0, 2, 1, 2],
x = [];
for(var i = 0;i<=b.length-1;i++)
x.push(a[i] - b[i]);
console.log(x);
const A = [1, 4, 3, 2]
const B = [0, 2, 1, 2]
const C = A.map((valueA, indexInA) => valueA - B[indexInA])
console.log(C) // [1, 2, 2, 0]
Here the map is returning the substraction operation for each number of the first array.
Note: this will not work if the arrays have different lengths
If you want to override values in the first table you can simply use forEach method for arrays forEach. ForEach method takes the same parameter as map method (element, index, array). It's similar with the previous answer with map keyword but here we are not returning the value but assign value by own.
var a = [1, 4, 3, 2],
b = [0, 2, 1, 2]
a.forEach(function(item, index, arr) {
// item - current value in the loop
// index - index for this value in the array
// arr - reference to analyzed array
arr[index] = item - b[index];
})
//in this case we override values in first array
console.log(a);
One-liner using ES6 for the array's of equal size in length:
let subResult = a.map((v, i) => v - b[i]); // [1, 2, 2, 0]
v = value, i = index
function subtract(operand1 = [], operand2 = []) {
console.log('array1', operand1, 'array2', operand2);
const obj1 = {};
if (operand1.length === operand2.length) {
return operand1.map(($op, i) => {
return $op - operand2[i];
})
}
throw new Error('collections are of different lengths');
}
// Test by generating a random array
function getRandomArray(total){
const pool = []
for (let i = 0; i < total; i++) {
pool.push(Math.floor(Math.random() * total));
}
return pool;
}
console.log(subtract(getRandomArray(10), getRandomArray(10)))
Time Complexity is O(n)
You can also compare your answer with a big collection of arrays.