Compare arrays as (multi-) sets

前端 未结 8 1704
梦如初夏
梦如初夏 2021-01-04 21:42

I\'m looking for an efficient way to find out whether two arrays contain same amounts of equal elements (in the == sense), in any order:

foo = {         


        
8条回答
  •  刺人心
    刺人心 (楼主)
    2021-01-04 21:59

    Using efficient lookup tables for the counts of the elements:

    function sameElements(a) { // can compare any number of arrays
        var map, maps = [], // counting booleans, numbers and strings
            nulls = [], // counting undefined and null
            nans = [], // counting nans
            objs, counts, objects = [],
            al = arguments.length;
    
        // quick escapes:
        if (al < 2)
            return true;
        var l0 = a.length;
        if ([].slice.call(arguments).some(function(s) { return s.length != l0; }))
            return false;
    
        for (var i=0; i -1)
                        counts[ind]++;
                    else
                        objs.push(val), counts.push(1);
                } else { // booleans, strings and numbers do compare together
                    if (typeof val == "boolean")
                        val = +val;
                    if (val in map)
                        map[val]++;
                    else
                        map[val] = 1;
                }
            }
        }
    
        // testing if nulls and nans are the same everywhere
        for (var i=1; i

    It still uses indexOf search amongst all objects, so if you have multisets with many different objects you might want to optimize that part as well. Have a look at Unique ID or object signature (and it's duplicate questions) for how to get lookup table keys for them. And if you don't have many primitive values in the multisets, you might just store them in arrays and sort those before comparing each item-by-item (like @Bruno did).

    Disclaimer: This solution doesn't try to get the [[PrimitiveValue]] of objects, they will never be counted as equal to primitives (while == would do).

    Here is the update on @Bruno's jsperf test of the answers, yet I guess only two objects (each of them present 500 times in the 10k array) and no duplicate primitive values are not representative.

提交回复
热议问题