0

Is there any sensible way to make a dictionary in Javascript where the keys are Set objects?

For context, my problem is that I have a list of lists and want to count the number of times each combination occurs, ignoring the order and repetition of elements. I can make a dictionary where the lists themselves are elements, but if I try the same with a set, it treats every set as the same key with value: [object Set].

As an example:

var list_of_lists = [[1,2], [1], [1], [2,1], [1,1]]
var count_of_id_combos = {}
var count_of_id_combo_sets = {}

list_of_lists.forEach(
    function(sub_list, index){
        count_of_id_combos[sub_list] = (count_of_id_combos[sub_list] || 0) + 1
        var set_of_sublist = new Set(sub_list)
        count_of_id_combo_sets[set_of_sublist] = (count_of_id_combo_sets[set_of_sublist] || 0) + 1

    }
)
console.log(count_of_id_combos) // -> Object {1: 2, 1,2: 1, 2,1: 1, 1,1: 1}
console.log(count_of_id_combo_sets) // -> Object {[object Set]: 5}

whereas I'd like the second object to be something like

Object {1: 3, 1,2: 2}

I've tried using Map as well and the same thing happens. The only solution I've come up with is manually filtering out duplicates and then sorting the lists, which works but seems overly complicated and I wondered if there was something I was missing.

5
  • 2
    You can have a Map that has instances of Set as keys. But this won't work because new Set([1]) === new Set([1]); //false each new set will give a new key even though the content is the same. Commented Jan 17, 2019 at 15:59
  • Are you sure? I seem to get the opposite behaviour, When I run the exact code as above but using a Map, I get Map(0) {[object Set]: 5} as the output. Commented Jan 17, 2019 at 16:04
  • @AndrewMcDowell: In your sample code, you are never using Maps - you are using objects, which can only have strings as keys; and the default ToString for Set returns [object Set] (e.g. try "" + new Set() to trigger it). Yury Tarabanko is talking about maps, which do not have that restriction on keys, so the set would not be stringified. Commented Jan 17, 2019 at 16:06
  • 1
    @AndrewMcDowell I am const map = new Map([[new Set([1]), 1], [new Set([1]), 2]]) try logging map Commented Jan 17, 2019 at 16:07
  • Ah I understand. I modified my code to use maps instead of objects but I'm still accessing them as if they were objects and not making use of the map functionality. Thank you both for the help, really appreciate the explanations. Commented Jan 17, 2019 at 16:15

1 Answer 1

1

One way to do what you want is to convert a set to a string; for example,

let map = new Map()

let setSet = new Set([3, 1, 2])
let setKey = Array.from(setSet).sort().join()
map.set(setKey, "foo")

let getSet = new Set([2, 1, 1, 3])
let getKey = Array.from(getSet).sort().join()
console.log(map.get(getKey))

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.