3

I have QMap and I want to make QSet the key of it, I couldn't do that because QSet is not comparable. for example:

QSet<int> intSet;
QMap<QSet<int>, char> charSet;

intSet.insert(1);
intSet.insert(2);
intSet.insert(3);

charSet.insert(intSet, '6');

Is there any way to make it work? and if I inherit from QSet and define operator < how should I implement it? i.e: What should be the logic of the comparison?

Note: I care too much about performance

MhdAljuboori
  • 475
  • 4
  • 15
  • 1
    You should probably tell us what your intention is with wanting to use a `QSet` as a key. – wkl Apr 19 '12 at 20:59
  • 2
    check this http://stackoverflow.com/questions/9126470/how-to-write-qhash-for-a-qsetsomeclass-container – AAlkhabbaz Apr 19 '12 at 21:02
  • @birryree I have a list of set and i want to reach to specific object depends on every set – MhdAljuboori Apr 19 '12 at 21:07
  • possible duplicate of [Mapping between sets of integers](http://stackoverflow.com/questions/7298103/mapping-between-sets-of-integers) – alexisdm Apr 19 '12 at 23:53

4 Answers4

5

You seem to know how to make it work: define an operator<(const QSet<int>&) function (I don't believe Qt requires that you subclass QSet to make this work, I know STL does not).

Obviously, implementing a comparator on an unordered set is going to be difficult. And doing it such that it runs in constant time is, I believe, impossible. You might try something like checking the size first, and then sorting and comparing the two contents as lists.

But broadly: don't do this. It's an abuse. Surely there is something you can use for the key of your set that is not a mutable data structure. Is the space of integers in the sets fixed and small (i.e. always in the range 0-1024 or whatnot)? Then try a bitmask stored in a QByteArray. etc...

Andy Ross
  • 11,699
  • 1
  • 34
  • 31
1

you can make a hash method like this

uint qHash(const QSet<int>& set) {
  uint seed = 0;

  for(int x : set) {
     seed ^= qHash(x) + 0x9e1559a9 + (seed << 6) + (seed >> 2);
  }
  return seed;
}

then your QMap will be like this

QMap<uint, char> charSet;

where uint is the result of previous method .

actually this way isn't stable 100% , it depends on your hash function.

AAlkhabbaz
  • 197
  • 1
  • 3
  • 13
  • if you define qHash function then you can use hashed structure directly in `QHash`, that is you may write `QHash, char>`. – mip Apr 19 '12 at 22:08
  • i used qHash for elements inside the set where qHash is defined not to all set – AAlkhabbaz Apr 19 '12 at 22:12
  • but as I can see you have defined qHash for whole `QSet` using predefined `qHash(int)`. BTW why do you add `0x9e1559a9` to the `seed` and shift `<< 6`, `>>2`? – mip Apr 19 '12 at 22:35
  • 1
    The above hash function doesn't work. **Don't use it**. Cf. http://stackoverflow.com/questions/9126470/how-to-write-qhash-for-a-qsetsomeclass-container?lq=1 for a correct `qHash(QSet)`. – Marc Mutz - mmutz Mar 14 '14 at 10:49
0

Assuming you're not worried about performance (and if you're using a container as a key I think that's a fair assumption to make) then I would do something like this.

QSet<int> intSet;
intSet << 1 << 2 << 3 << 3 << 4;

QVector<int> intVector;
intVector.reserve(intSet.size());
qCopy(intSet.begin(), intSet.end(), std::back_inserter(intVector)); // QVector doesn't have a std::vector range constructor atm
qSort(intVector);

QHash<QVector<int>, char> charHash;
charHash[intVector] = '6';

This will be very slow to add, but the lookups should be (comparatively) fast.

I would suggest you come up with a better key though. Perhaps a simple class with a fixed number of ints which you just define the necessary operators for it to go in a map/hash.

Marc Mutz - mmutz
  • 24,485
  • 12
  • 80
  • 90
Samuel Harmer
  • 4,264
  • 5
  • 33
  • 67
0

It seems like you don't need a value semantics. Wo why not use:

QHash<QSet<int> *, char> charSet;
//then to insert a set
charSet.insert(& intSet, '6');

However for each set there is only one character that corresponds with a set, so why don't you extend QSet and add additional member?

mip
  • 8,355
  • 6
  • 53
  • 72
  • Those aren't compatible semantics though (whether they match the OP's requirements is an open question, of course). The question asked for a container that treats e.g. all empty sets as equal and stores only one value. Storing a pointer will store one value for each distinct empty set inserted. – Andy Ross Apr 19 '12 at 21:43
  • @AndyRoss if author asks for the idea on how to implement sets comparison, then I doubt he needs this comparison. Sets comparison can be implemented in undefined number of ways. – mip Apr 19 '12 at 21:55