Can anyone suggest a way to generate an integer key from a class?

I am new to computer science and I think it has something to do with hash function.

I have a class in cpp:

class Car{
    public:
    int fleetId;
    OwnershipEnum owner;
    int buildDate;
    bool hasFourDoors;

    ... with many other members
};

      

Now, my problem is how to "scientifically" generate an integer key based on the 4 members that I am listing?

I can think of a simple way 10000*int(fleetId) + 1000 * int(owner) + 100Γ—int(buildDate) + int(hasFourDoors)

I think the key is ideally contiguous, so I can store all Car objects in an array and use that generated key to access the car object directly.

***** according to the comments: cars are all different, no cars are alike ********

***** these four members are static: they will not change after creation *****

Can anyone point me to the correct solution here?

thank

+3


source to share


3 answers


You can create a method to get it using std::hash

: This is a simple example.



std::size_t CarHash(const Car& car)
{
    std::size_t h1 = std::hash<int>{}(car.fleetId);
    std::size_t h2 = std::hash<int>{}(int(car.owner));
    std::size_t h3 = std::hash<int>{}(int(car.isGoodCondition));
    std::size_t h4 = std::hash<int>{}(int(car.isBooked));
    return h1^(h2 << 1)^(h3 << 2)^(h4 << 3);
}

      

+3


source


The combination of these members is not enough to uniquely identify a vehicle: Imagine two vehicles having the same fleet (due to the fact that they are part of the same fleet), the same owner, and both booked and in good condition. This will result in the same identifier if you compute it based on these properties. As @jsheeran suggested, you can use the license plate as a unique identifier.

Otherwise, add another member for id to your car class and get a static variable for the global, incrementing the key on each call to the car's constructor. However, keep in mind that this is just an example implementation, and you may want to have another class for managing keys, because this implementation will never be "free" keys.



class Car{

public:
    Car() : id(++nextId) {}

    const unsigned id;

private:
    static unsigned nextId;
};

unsigned Car::nextId = 0U; // initialize in your cpp using the cars

int main()
{
    Car a;
    Car b;
    Car c;

    std::cout << a.id << b.id << c.id; // will print 012
}

      

Another suggestion is to use a GUID. Depending on your platform or libraries used, you can find a solution here, for example: https://msdn.microsoft.com/en-us/library/ms688568(VS.85).aspx

+3


source


Suppose you need a non-collision key and all fields can take any value in their range, you will need to use the key sizeof (int) + sizeof (OwnershipEnum) + 2 bits to avoid all collisions, or 66 bits.This can be considered acceptable and calculated as follows:

struct key {
    int fleetId;
    OwnershipEnum owner;
    char bools;

    key(Car _myCar) : 
        fleetId(_myCar.fleetId), 
        owner(_myCar.owner), 
        bools(!!_myCar.isGoodCondition & !!_myCar.isBooked << 1 ) 
    {}

    bool operator ==(key other) { return fleetId == other.fleetId && owner == other.owner && bools == other.bools; }
};

      

then follow these steps:

  Car first{1, (OwnershipEnum)2, false, true};
  Car second{1, (OwnershipEnum)2, false, true};
  Car third{8, (OwnershipEnum)1, true, true};

  key k1{first}, k2{second}, k3{third};

  std::cout << (k1 == k2) << "\n"; //true
  std::cout << (k2 == k3) << "\n"; //false
  std::cout << (k3 == k1) << "\n"; //false

      

full program: http://cpp.sh/2vv2a

This is obviously a wrong assumption, but you can try to reduce the key size if you can do your best for fleetId to 16 bits, or shorten the OwnershipEnum, for example

0


source







All Articles