0

I am trying to remove the empty array elements (from a csv file) by using the splice() function.

The array elements are stored inside csv.data:

csv.data.forEach(function(item,index) {
    if (item.length < 2) { // don't want anything less than two
        csv.data.splice(index,1); 
        }
    });

This works, but it still returns me two empty arrays (lines) in the csv file, originally, there are six empty lines, but it skips the two empty lines.

Am I doing anything wrong?

This is the csv.data

[
 [
  "1212",
  "okay",
  ""
 ],
 [
  ""
 ],
 [
  ""
 ],
 [
  ""
 ],
 [
  ""
 ],
 [
  ""
 ],
 [
  ""
 ]
]

Expected

[
 [
  "1212",
  "okay",
  ""
 ],
]
Dhiraj
  • 2,687
  • 2
  • 10
  • 34
  • 5
    iterating while splicing ... not a good idea. – Nina Scholz Mar 22 '18 at 13:15
  • 2
    Possible duplicate of [Remove empty elements from an array in Javascript](https://stackoverflow.com/questions/281264/remove-empty-elements-from-an-array-in-javascript) – Herohtar Mar 22 '18 at 13:16
  • @NinaScholz it absolutely correct. Any type of modifying of location of elements of an array, whether moving, adding, or removing, in a forEach could have undesired consequences. You would be better using a `for` loop and adding logic to keep track of where you were (but only as a fun way to understand the logic and why it breaks). But, that's also not the best solution here. I just thought I would reiterate why these modifications are not recommended in a forEach. – adprocas Mar 22 '18 at 13:19
  • What is the content of `csv.data` ? – Weedoze Mar 22 '18 at 13:19
  • posted @Weedoze Answer updated – Dhiraj Mar 22 '18 at 13:23
  • 1
    That update is not that helpful, it looks now like an array of array. Could you try doing `console.log(JSON.stringify(csv.data, null, " "))` and copy post that. – Keith Mar 22 '18 at 13:24
  • @Keith updated answer – Dhiraj Mar 22 '18 at 13:26

3 Answers3

6

It's not a good idea to use splice inside the loop. You can miss some indexes. You can use filter function instead of forEach

var csv = { data: [["1212", "okay", ""], [""], [""], [""], [""], [""], [""]] };

csv.data = csv.data.filter(items => items.length > 1);

console.log(csv.data);
Reinstate Monica Cellio
  • 25,975
  • 6
  • 51
  • 67
Suren Srapyan
  • 66,568
  • 14
  • 114
  • 112
  • Already tried this, this somehow returns true and false for `csv.data` – Dhiraj Mar 22 '18 at 13:16
  • 2
    It will return an array with same data, but filtered., which is in the `csv.data`. – Suren Srapyan Mar 22 '18 at 13:17
  • This returns `false` I already tried doing this. Maybe has to do something with `csv.data` being an object – Dhiraj Mar 22 '18 at 13:19
  • 2
    Please update the question and add an example of `csv.data` as this answer is 100% correct, for the question as it currently stands. – Reinstate Monica Cellio Mar 22 '18 at 13:19
  • Hard to tell what your update is, but it looks like an array of arrays.. So just do a map followed by a filter. – Keith Mar 22 '18 at 13:23
  • @SurenSrapyan can you check my updated question? This answer won't work I guess – Dhiraj Mar 22 '18 at 13:24
  • @zuif If you run this answer on the array from the updated question you get an array with a single array element in it: `[["121", "okay", ""]]` – Herohtar Mar 22 '18 at 13:25
  • `[ [ "1212", "okay", "" ], [ "" ], [ "" ], [ "" ], [ "" ], [ "" ], [ "" ] ]` – Dhiraj Mar 22 '18 at 13:27
  • 1
    I've added the array and a code snippet, to show this working exactly as described. – Reinstate Monica Cellio Mar 22 '18 at 13:29
  • 1
    @Archer Thanks. – Suren Srapyan Mar 22 '18 at 13:30
  • Guys, this code is perfectly legit. But for my context doesn't work, array filter just returns `false` so my array is just false. Nina Scholz's answer below worked for me, so I am going to accept that. – Dhiraj Mar 22 '18 at 13:38
  • 1
    @zuif - you're 100% wrong. This code works and if you just click a simple button then you'd see it. If this answer is in any way incorrect then it's because you have failed to describe the problem. – Reinstate Monica Cellio Mar 22 '18 at 13:43
  • @Archer That's correct. And that's what I am saying. This code is 100% correct, but in my `context` didn't worked. That being said, I am 100% incapable of describing my `context`, so it's 100% my mistake – Dhiraj Mar 22 '18 at 13:44
  • @zuif There is no context in which `filter` returns false unless you are doing something horribly wrong and overwriting the method on the array prototype. – Herohtar Mar 22 '18 at 14:15
1

If you also wanted to remove empty elements from the top array, you could do another filter.

eg.

const a = [ [ "1212", "okay", "" ], [ "" ], [ "" ], [ "" ], [ "" ], [ "" ], [ "" ] ];

const ret1 = a.map((b) => b.filter((f) => f));
console.log(ret1);

//if you also want to remove empty elements from top array.
const ret2 = ret1.filter((f) => f.length);
console.log(ret2);
Keith
  • 22,005
  • 2
  • 27
  • 44
0

You could iterate the array from the end and splice without colliding with the index.

var array = [["1212", "okay", ""], [""], [""], [""], [""], [""], [""]],
    i = array.length;
    
while (i--) {
    if (array[i].length < 2) {
        array.splice(i, 1);
    }
}

console.log(array);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392