skip to Main Content

Coming from a different language (where such thing was trivial), I am struggling to express a list of pairs:

  • Each pair consists of two primitives (strings, or numbers)
  • Each value can repeat multiple times, but a combination must be unique:
a, k
a, m
b, m
b, n

The 2 features I need are:

  • Be able to add a pair, knowing that if a pair repeats, it won’t be added (e.g. if I try to add a, k to the above list, the second instance won’t be added
  • I should be able to check if the pair is in the list. E.g. if I check b, n it would return true, and b, p would return false.

What’s the suitable implementation in typescript?

Originally I was thinking of Set<[string, string]>:

const a = new Set<[string, string]>();
a.add(['a', 'k']);
a.add(['a', 'm']);
a.add(['b', 'm']);
a.add(['b', 'n']);
...

But of course the issue is that it compares object, so a.has(['a', 'b']) returns false.
So what are the other options?

2

Answers


  1. How about creating your own utility for this?

    type Item = string | number
    type ItemPair<T extends Item> = [T, T]
    
    class ItemPairHolder<T extends Item> {
      private holder: Map<Item, Set<Item>>;
    
      public constructor() {
        this.holder = new Map();
      }
    
      public add(pair: ItemPair<T>): void {
        const [key, value] = pair;
        const set = this.holder.get(key) ?? new Set();
    
        set.add(value);
        this.holder.set(key, set);
      }
    
      public has(pair: ItemPair<T>): boolean {
        const [key, value] = pair;
        return this.holder.get(key)?.has(value) ?? false;
      }
    }
    

    When using it with your example:

    const holder = new ItemPairHolder<string>();
    holder.add(['a', 'k']);
    holder.add(['a', 'm']);
    holder.add(['b', 'm']);
    holder.add(['b', 'n']);
    
    console.log(holder.has(['b', 'n'])); // true
    console.log(holder.has(['b', 'p'])); // false
    
    Login or Signup to reply.
  2. JS Set checks element equality using Object.is. Thus, for arrays it compares if it is the same instance or the array.

    See Set in MDN

    See Equality comparisons and sameness

    I would consider a class holding your arrays in stringified form:

    class ArraySet<T extends any[]>  {
        values = new Set<string>();
        add: (arr: T) => this = (arr) => {
            this.values.add(JSON.stringify(arr));
            return this;
        }
    
        has: (arr: T) => boolean = (arr) => {
            return this.values.has(JSON.stringify(arr));
        }
    }
    
    const a = new ArraySet<[string, string]>();
    a.add(['a', 'k']);
    a.add(['a', 'm']);
    a.add(['b', 'm']);
    a.add(['b', 'n']);
    
    console.log(a.has(['a', 'k']))
    

    See also: Storing arrays in ES6 Set and accessing them by value

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search