Simple ways:
var arr = [1,2,,3,,-3,null,,0,,undefined,4,,4,,5,,6,,,,];
arr.filter(n => n)
// [1, 2, 3, -3, 4, 4, 5, 6]
arr.filter(Number)
// [1, 2, 3, -3, 4, 4, 5, 6]
arr.filter(Boolean)
// [1, 2, 3, -3, 4, 4, 5, 6]
or - (only for single array items of type "text")
['','1','2',3,,'4',,undefined,,,'5'].join('').split('');
// output: ["1","2","3","4","5"]
or - Classic way: simple iteration
var arr = [1,2,null, undefined,3,,3,,,0,,,[],,{},,5,,6,,,,],
len = arr.length, i;
for(i = 0; i < len; i++ )
arr[i] && arr.push(arr[i]); // copy non-empty values to the end of the array
arr.splice(0 , len); // cut the array and leave only the non-empty values
arr // [1,2,3,3,[],Object{},5,6]
via jQuery:
var arr = [1,2,,3,,3,,,0,,,4,,4,,5,,6,,,,];
arr = $.grep(arr,function(n){ return n == 0 || n });
arr // [1, 2, 3, 3, 0, 4, 4, 5, 6]
UPDATE - just another fast, cool way (using ES6):
var arr = [1,2,null, undefined,3,,3,,,0,,,4,,4,,5,,6,,,,],
temp = [];
for(let i of arr)
i && temp.push(i); // copy each non-empty value to the 'temp' array
arr = temp;
arr // [1, 2, 3, 3, 4, 4, 5, 6]
Remove empty values
['foo', '',,,'',,null, ' ', 3, true, [], [1], {}, undefined, ()=>{}].filter(String)
// ["foo", null, " ", 3, true, [1], Object {}, undefined, ()=>{}]
delete
will delete the object property, but will not reindex the array or update its length. This makes it appears as if it is undefined:
> myArray = ['a', 'b', 'c', 'd']
["a", "b", "c", "d"]
> delete myArray[0]
true
> myArray[0]
undefined
Note that it is not in fact set to the value undefined
, rather the property is removed from the array, making it appear undefined. The Chrome dev tools make this distinction clear by printing empty
when logging the array.
> myArray[0]
undefined
> myArray
[empty, "b", "c", "d"]
myArray.splice(start, deleteCount)
actually removes the element, reindexes the array, and changes its length.
> myArray = ['a', 'b', 'c', 'd']
["a", "b", "c", "d"]
> myArray.splice(0, 2)
["a", "b"]
> myArray
["c", "d"]
Best Answer
Problem Statement
We have an array of values,
vals
and runlengths,runlens
:We are needed to repeat each element in
vals
times each corresponding element inrunlens
. Thus, the final output would be:Prospective Approach
One of the fastest tools with MATLAB is
cumsum
and is very useful when dealing with vectorizing problems that work on irregular patterns. In the stated problem, the irregularity comes with the different elements inrunlens
.Now, to exploit
cumsum
, we need to do two things here: Initialize an array ofzeros
and place "appropriate" values at "key" positions over the zeros array, such that after "cumsum
" is applied, we would end up with a final array of repeatedvals
ofrunlens
times.Steps: Let's number the above mentioned steps to give the prospective approach an easier perspective:
1) Initialize zeros array: What must be the length? Since we are repeating
runlens
times, the length of the zeros array must be the summation of allrunlens
.2) Find key positions/indices: Now these key positions are places along the zeros array where each element from
vals
start to repeat. Thus, forrunlens = [2,2,1,3]
, the key positions mapped onto the zeros array would be:3) Find appropriate values: The final nail to be hammered before using
cumsum
would be to put "appropriate" values into those key positions. Now, since we would be doingcumsum
soon after, if you think closely, you would need adifferentiated
version ofvalues
withdiff
, so thatcumsum
on those would bring back ourvalues
. Since these differentiated values would be placed on a zeros array at places separated by therunlens
distances, after usingcumsum
we would have eachvals
element repeatedrunlens
times as the final output.Solution Code
Here's the implementation stitching up all the above mentioned steps -
Pre-allocation Hack
As could be seen that the above listed code uses pre-allocation with zeros. Now, according to this UNDOCUMENTED MATLAB blog on faster pre-allocation, one can achieve much faster pre-allocation with -
Wrapping up: Function Code
To wrap up everything, we would have a compact function code to achieve this run-length decoding like so -
Benchmarking
Benchmarking Code
Listed next is the benchmarking code to compare runtimes and speedups for the stated
cumsum+diff
approach in this post over the othercumsum-only
based approach onMATLAB 2014B
-Associated function code for
rld_cumsum.m
:Runtime and Speedup Plots
Conclusions
The proposed approach seems to be giving us a noticeable speedup over the
cumsum-only
approach, which is about 3x!Why is this new
cumsum+diff
based approach better than the previouscumsum-only
approach?Well, the essence of the reason lies at the final step of the
cumsum-only
approach that needs to map the "cumsumed" values intovals
. In the newcumsum+diff
based approach, we are doingdiff(vals)
instead for which MATLAB is processing onlyn
elements (where n is the number of runLengths) as compared to the mapping ofsum(runLengths)
number of elements for thecumsum-only
approach and this number must be many times more thann
and therefore the noticeable speedup with this new approach!