-->

What use cases are there in JavaScript for Sparse

2020-04-08 05:17发布

问题:

What possible programming use could you have where a sparse array would be better than an (regular) object?

By sparse array I mean one where:

arr = [];                             //Initialize
arr[0] = 'W';
arr[1] = 'T';
arr[3] = 'F';

console.log(arr[0] !== undefined)    //true
console.log(arr[1] !== undefined)    //true
console.log(arr[2] === undefined)    //true
console.log(arr[3] !== undefined)    //true

Or more formally:

An object, O, is said to be sparse if the following algorithm returns true:

1. Let len be the result of calling the [[Get]] internal method of O with argument 
"length".

2. For each integer i in the range 0≤i<ToUint32(len)
    a. Let elem be the result of calling the [[GetOwnProperty]] internal method of O     
    with argument ToString(i).

    b. If elem is undefined, return true.

3. Return false.

ECMA 262 5.1 - 15.4 Array Objects

Moreover, the ECMA 262 5.1 Standard further defines length specifically as:

The length property of this Array object is a data property whose value is always numerically greater than the name of every deletable property whose name is an array index.

So the example above, arr.length === 4 despite there only being three elements defined.

In fact, according to the standard, any Number greater than 3 is a valid length for arr, including Math.PI.

Consequently, does this mean that no one should use:

for(var i=0; i<arr.length; i++)
    //Cannot trust arr[i] exists

and instead it would be more appropriate to use

for(key in arr)
    //Always exists

I've never encountered an intentional one in the wild, and really only began thinking about it while reading an odd Q&A here, and now I'm a little unsettled.

I've long known that there's not a neat way to remove an element from an Array, but now I'm even more confused as to why you would intentionally leave a hole, let alone define a standard where length can be any number greater than the last defined element.

If I wanted random key value pairs, I'd use an Object. If I want to be able to cleanly iterate, I use an Array. Am I missing something?

Note, I'm looking for a specific use case, or a class of generalized use cases not a reference to the standards, or an opinion. I know it's allowed, and I already have an opinion. :)

To add a test or see some of the ones I've seen where the Array standard works in unexpected ways, check out this fiddle

Sorry if this is a bit abstract. Been thinking about it all night.

回答1:

One possible use-case for sparse arrays that I've come across in real usage is for a heat-map.

Start with your map being an empty array of X × Y elements. Load your data, and populate it into the map by incrementing the array elements at the relevant co-ords.

Another similar example might be a battleship game, where boats are placed into an empty grid by populating the array elements at the appropriate co-ordinates.

That's not to say this is this only way to do this, or even the best way -- both examples can quite easily be achieved without using a sparse array -- but the question was asking for use cases, so there you go.



回答2:

It depends on what your definition of "sparse array" is. For example, you want to express in code something like

"2 items of product 51472 and 1 item of product 81369"

Then, according to one possible definition (a, so to speak, "mathematical" definition) that thought you want to express in code is a "sparse array". Nothing wrong with that, the thought is the use case. The correct implementation is, use plain Objects {}.

The other possible definition of "sparse array" is, in the above scenario, just because all occurring keys are natural numbers, you think it should be an array ([]) - a, so to speak, "javascriptological" definition. This second definition of "sparse array" has absolutely no use cases. Zero. It is wrong. Very very very very very very wrong. Bad. Pure 100% bad, not a fraction of an atom of goodness.

It's completely unnecessary, because {} does what you want, and using [] instead will make you write inefficient slow code, but you won't find the error until years later. Don't do it.

How that? read this