Pregunta

I am working on an application that have some categories. The aim is to store the categories in a value.
First, I choosed to store them in an int.
Categories : 0, 1, 2, 3...
Then I do a bitmask operation to find which category was selected.
But the problem is that I can't store more that 31 categories is this int.

Is there any way to make such system ? I don't want to go threw the unlimited number of categories but maybe over 64.
The target language is C# but any other solution could be fine.

Thanks a lot !

¿Fue útil?

Solución

Consider using System.Collections.BitArray, which is an arbitrary-length array of bits. You can do intersections (AND), unions (OR), and complements (NOT).

You can now haver more than 32 categories keyed by integers:

public static class Categories
{
   public const int Category1 = 1;
   public const int Category2 = 2;
    //...
   public const int Category3123 = 3123;
   public const int Max = 5000;
}

BitArray myBitset = new BitArray((int)Categories.Max);
myBitSet.Set(Categories.Category1);
myBitSet.Set(Categories.Category4);

I used ints rather than enums to avoid all the casts to int that are necessary when using BitArray, but obviously you could encapsulate these in a class that deals with categories.

Otros consejos

I am not sure I correctly understand your question so here are 2 answers:

If you want to categorize an object but it can hold only one category at a time you can perfectly choose just to store the category number in the int - no need for bitmasking.

If you want to store different flags/categories/options that should all be either true or false for a given object then you should go for a longer bitmask. An array of bools is a good idea - no need to do bit ops to get and set the values and I am pretty sure the compiler does it's best to optimize space usage (as you know a single bool variable is actually one byte but I assume that if you create many bool variables they will actually be stuffed insisde the least possible space.) Anyway you can always opt for your own implementation with long, which is 64 bits, or even BigInteger - unlimited number of digits, you just initially have to set it to 1*10^x where x is the number of the larges bit position you want to have access to.

If you define you categories like this:

public enum Categories
{
    Category1 = 0x0001,
    Category2 = 0x0002,
    Category3 = 0x0004,
    Category4 = 0x0008,
    Category5 = 0x000F,
    Category6 = 0x0010,
    Category7 = 0x0020,
    Category8 = 0x0040,
    // etc...
}

Then you can use them like this:

var myCategories = Categories.Category1 | Categories.Category4;

if(myCategories | Categories.Category1 > 0)
{
    // do something for category 1....
}

Why are you using bit masks here? Is there an overarching concern for storage efficiency? Otherwise just use a HashSet of your categories.

Conceptually a bit set and a conventional set container are identical, a bit set is just a particular implementation with special performance characteristics.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top