Search code examples
c#listlinqasp.net-core-mvcbitwise-operators

Bit wise and operation on list and convert value to comma separated string


I have a list which returns an ID, Type and value. The IDs are stored as power of 2. Sample data below

var _data = await _context.clubs.Where(x => x.Type == "NewTown").ToListAsync();
ID Type Value
1 NewTown Test1
2 NewTown Test2
4 NewTown Test3

I have a view model which stores IDs from this table by adding them like if I select first and third it will save 5 similarly if I select first and second it will save 3.

These values will be saved in a different table where I can't store the Ids as comma separated values because it would eventually b sent as a token and if I have many fields the token would exceed the length that's why I'm saving the sum of the Ids.

Now what I want to do is while displaying these values I want to show Test1 , Test3 if 5 is saved. Now I know if I do a bit wise and operation with the array and the selected value it will give me the values like this example below.

var savedVal= 5;
var testArray = new int[] {1,2,4,8,16,32,64,128};
testArray .Select(x => new { savedVal= x, Enabled = ((savedVal & x) > 0) }).Dump();
savedVal Enabled
1 True
2 False
4 True
8 False
16 False
32 False
64 False
128 False

This will give me enabled "true" for the values that were selected.

Now what I want to know is how can I achieve this for my list scenario where I have 3 fields in the list and I want to have the values of enabled ones as a comma-separated string like "Test1, Test3" for the example I shared.


Solution

  • Using a combination of Linq: Join, Where, Select, ToArray, with String.Join to produce a list of Test Values from the DBContext by joining your returned list of savedVals where Enabled = true

    //a test object to simulate your DBContext
    var testdbcontext = new List<dynamic> 
    { 
        new { Id = 1, Type = "NewTown", Value = "Test1" }, 
        new { Id = 2, Type = "NewTown", Value = "Test2" }, 
        new { Id = 4, Type = "NewTown", Value = "Test3" }
    };
    
    var savedVal= 5;
    var testArray = new int[] {1,2,4,8,16,32,64,128};
    
    Console.WriteLine(String.Join(",", 
        testdbcontext
       .Join(testArray.Select(x => new { savedVal= x, Enabled = ((savedVal & x) > 0) })
       .Where(b => b.Enabled)
       .Select(c => c.savedVal),
                    a => a.Id,
                    b => b,
                    (a, b) => new string (a.Value)).ToArray()));
    

    Prints:

    //Test1,Test3