1

I've made this post last year and today, I assume things can be simplified.

I need to remove an item from an array but by the index. When by the index, it does not matter if the array has same values. Your typical example:

let arr = [1,2,3,2,1] // just an array, not array with objects
let x = 1;

// This will not be an expected result:
// Find all values that is equal to 1 then remove
arr.filter(num => num !== x) //=> [2,3,2]

My expectation is when I remove the last element (1), for example, the array should be [1,2,3,2]:

let index = 4; // which is the last "1" in the array
let indexVal = arr.indexOf(4) // 1
let newArray = arr.splice(indexVal, 1) //=> [1,2,3,2]

Now, it's 2017, almost '18, is there a shorter way (es5/6) of doing this without any polyfil?

Edit:

Think of this as a todo:

<ul>
  <li>me</li>
  <li>me</li> // click to delete this one
  <li>you</li>
  <li>me</li>
</ul>

To correctly remove that item, I have to delete by the index not value

Sylar
  • 8,631
  • 20
  • 72
  • 139

4 Answers4

7

The Array.filter callback gives 2 arguments, number and index and you can filter the array this way.

let arr = [1,2,3,2,1] 
let x = 4; //suppose you want to remove element at 4th index

let editedArray = arr.filter((num, index) => index !== x) //editedArray = [1,2,3,2]

EDIT:

The third parameter gives the whole array. Thanks @Oliver for pointing this out in comment

Ajay Gaur
  • 4,400
  • 4
  • 31
  • 49
  • 1
    I was "playing" with `filter` but could not get it, I forgot to add in the index `(val, index)`. Thanks – Sylar Nov 23 '17 at 07:52
  • 2
    Just for completion: The filter function has also a third parameter where you get the whole array you currently operating on. – Oliver Nov 23 '17 at 07:54
  • *Shortest* version: `arr.filter((_, i) => i !== x)` – Kutyel Nov 23 '17 at 15:27
5
arr.splice(index, 1);

or if you specifically want to remove the last element:

arr.pop();

No indexOf call. The indexOf call never should have been there; it only ever looked like it worked because indexOf returns -1 for an element that isn't present, and splice treats negative indices as counting from the end of the array.

Also, splice modifies the array in place and returns an array of removed elements, so assigning its return value the way you were doing is misleading.

user2357112 supports Monica
  • 215,440
  • 22
  • 321
  • 400
  • You might want to add that both `.splice()` and `.pop()` return the removed element/s so `let newArray = arr.splice(indexVal, 1)` will actually make `newArray = 1` – Ante Jablan Adamović Nov 23 '17 at 07:54
  • So when I `arr.length` what's the amount? I havent tried this as yet. – Sylar Nov 23 '17 at 07:54
  • @Sylar by the documentation `.splice(indexFromWhichToStartRemoving,numberOfElementsToRemove)` and since it mutates the actual array it returns the elements that were removed. `.pop()` removes the very last element of the array also mutates the array and returns that 1 removed element. – Ante Jablan Adamović Nov 23 '17 at 07:57
  • @AnteJablanAdamović: It'd be `newArray = [1]`, not `newArray = 1`, but yeah, that's worth mentioning. – user2357112 supports Monica Nov 23 '17 at 07:58
  • 1
    Hi. No pop. It needs to be flexible. Think of it as a todo list with same values and a user deletes either. Only the deleted one should be removed ;) – Sylar Nov 23 '17 at 08:00
3

The only way I can think of is the one we use in Redux every day:

const arr = [1, 2, 3, 2, 1]
const index = 4 // index of the item you want to remove
const newArr = [...arr.slice(0, index), ...arr.slice(index + 1)]
console.log(newArr) // [1, 2, 3, 2]

It might not be the shortest but it is more 2017 and it is immutable, which is very important!

Kutyel
  • 6,297
  • 2
  • 26
  • 55
1

Ajay's answer might be what you're looking for. Anyway, there are people like me who prefer slightly-more-lines-but-more-readable/rewritable/maintable solution, I'd do it this way:

function removeElementByIndex(arr, x) {
    var newArr = [];
    for(var i = 0; i < arr.length; i++) {
        if(i != x) {
            newArr.push(arr[i]);
        }
    }
    return newArr;
}
// Usage
removeElementByIndex([1, 2, 3, 2, 1], 4);// outputs: [1, 2, 3, 2]

Now, it's 2017, almost '18, is there a shorter way (es5/6) of doing this without any polyfil?

LOL! Many basic things not yet implemented. We'll have to wait for 2118 or another programming language to replace JS (oh wait, there's one, aka jQuery :P ).

evilReiko
  • 16,552
  • 21
  • 76
  • 90