1

I have a list of List<int> (List<List<int>>). The list consists of gaming bets of startnumbers in races. Lets say i choose three options in the first race, then one option in the remaining 6 races. This adds up to three combinations of bets.

A List<List<int>> of three unique rows(bets) would look like this:

[0] 1  [0] 2  [0] 3
[1] 1  [1] 1  [1] 1
[2] 1  [2] 1  [2] 1
[3] 1  [3] 1  [3] 1
[4] 1  [4] 1  [4] 1
[5] 1  [5] 1  [5] 1
[6] 1  [6] 1  [6] 1

When i submit the bet, i want to group the single bets into smaller grouped bets (maybe a List<List<string>>?) that mathematically represent the list above, so according to the above example:

[0] "1,2,3"
[1] "1"
[2] "1"
[3] "1"
[4] "1"
[5] "1"
[6] "1"

I have found similar solutions related to the topic Cartesian-product. But none seems applicaple to this problem. Any ideas?

I found this Reverse Cartesian Product , which describes my problem, but i cant really translate this answer into c# from java.

EDIT: Just to clarify on the questions in the comments, each bet always consist of 7 races, so if i chose bet #1 in race 2-7 and then bet on the #1,#2,#3 in the first race. My function creates three rows of List with a .Count == 7. I was just trying to illustrate the contents of the list. One would in c# initiate a new list this way:

List<List<int>> list = new List<List<int>> { new List<int> { 1, 1, 1, 1, 1, 1, 1 }, new List<int> { 2, 1, 1, 1, 1, 1, 1 }, new List<int> { 3, 1, 1, 1, 1, 1, 1 } };
telkert
  • 11
  • 2
  • 1
    Unclear what "mathematically represent the list above" means, not sure what the goal is, what's wrong with List> ? – Andrew Nov 06 '19 at 13:36
  • 1
    Why are the races 1 to 6 like this if you have only 1 options `[1] 1 [1] 1 [1] 1` instead of `[1] 1` ? A `List>` doesn't need to be rectangular – Cid Nov 06 '19 at 13:38
  • 1
    Just to extend @Cid's comment in case you want to look up information on this, `List>` is **jagged** (though not an array in this case, you might want to look up "jagged array" to understand the gist). – Flater Nov 06 '19 at 13:44
  • What if I have `[0] 3 [0] 2 [0] 3`? Should the result be `[0] "3,2,3"` or `[0] "3,2"` or `[0] "2,3"`? – Dmitry Bychenko Nov 06 '19 at 13:52
  • Just to clarify, the list need to contain exactly 7 bets each time. Its always 7 races. So the list[0] nr is always the bet # in the first race, the list[1] the bet # in race 2 etc. – telkert Nov 06 '19 at 15:07

3 Answers3

1

It seems like you want to remove duplicate int values on every row (= item of the top list), but retain the rows themselves even if they are duplicates of each other.

This can be achieved by using a Select() and Distinct():

var bets = new List<List<int>>()
{
    new List<int>() { 1 , 2 , 3 },
    new List<int>() { 1 , 1 , 1 },
    new List<int>() { 1 , 1 , 1 },
    new List<int>() { 1 , 1 , 1 },
    new List<int>() { 1 , 1 , 1 },
    new List<int>() { 1 , 1 , 1 },
    new List<int>() { 1 , 1 , 1 },
}

var reducedBets = bets.Select(bet => bet.Distinct());

reducedBets now effectively equals the same as:

new List<List<int>>()
{
    new List<int>() { 1 , 2 , 3 },
    new List<int>() { 1 },
    new List<int>() { 1 },
    new List<int>() { 1 },
    new List<int>() { 1 },
    new List<int>() { 1 },
    new List<int>() { 1 },
}

The notation you've used in your answer is unclear to me (weird index usage), but I infer this is what you want it to be?

Flater
  • 12,908
  • 4
  • 39
  • 62
  • I think you're starting with different lists then the op. The op seems to have 3 lists of 7 bets each. This starts with 7 lists of 3 bets per race. –  Nov 06 '19 at 13:52
  • @Knoop: I find OP's example notation unclear, but OP's description of the data seems to conform to my interpretation, at least to my understanding. _"Lets say i choose three options in the first race, then one option in the remaining 6 races"_ suggests to me OP has a collection with 7 items in which the last 6 are all the same. – Flater Nov 06 '19 at 13:55
  • I agree that it's unclear. That's why I tried to emphasize "think" and "seems". However I disagree with the op's description confirming your interpretation. My feeling comes from the fact that there seems to be indexes before the values, in your interpretation the index of the value (`[6] 1` would be value 1 at index 6) would be the index of the list the value resides in, which for me makes less sense then it being the index of the value inside the list it resides in. However this is a matter of interpretation, I did not downvote or claim your answer is guaranteed wrong. –  Nov 06 '19 at 14:38
  • Just to clarify, the list need to contain exactly 7 bets each time. Its always 7 races. So the list[0] nr is always the bet # in the first race, the list[1] the bet # in race 2 etc. – telkert Nov 06 '19 at 15:08
  • @telkert: This feels counterintuitive. Why is the top list not a list of races with the "bottom" list being a list of bets for that particular race? Your data structure feels wrong for the information it represents, which is effectively why you're dealing with these forced duplicate values in the first place. – Flater Nov 06 '19 at 15:11
0

Instead of 0,1,2,3,4,5,... you can use 1,2,4,8,16,... this way you can combine bets using bit-wise or operator (or simply sum them):

[0] 1 | 2 | 4 (equals 7)
[1] 1 | 1 | 1 (equals 1)

and to know that if it contains an element simply you can use bit-wise and (&) so

if(bet & 4 == 4) it contains 4;
if(bet & 8 == 8) it contains 8;

and so on.

So bet that contains 1,8,16 would be (1+8+16 or 1|8|16 = 25);

0 means no bet is made.

So you can still have all combination of bets in a single int.

Ashkan Mobayen Khiabani
  • 33,575
  • 33
  • 102
  • 171
  • This is susceptible to integer overflow for a sufficient amount of races (32+ to be specific), as your computational ability is capped by the amount of binary digits in an int (32) as opposed to the amount of possible values an int can have (2,147,483,647 assuming you only use positive ints and are not using `uint`) – Flater Nov 06 '19 at 13:47
  • Well, I'm well aware of that, but from the looks of the question and as I little knowledge of bets, it can't be much. – Ashkan Mobayen Khiabani Nov 06 '19 at 14:30
  • On top of that, it's a readibility argument. Your suggestion isn't impossible but I would flag it in a code review as unnecessarily contrived and detracting from readability. Bit flags have their use but they do not exist to replace collections/lists altogether, which is what you're suggesting here. – Flater Nov 06 '19 at 15:23
0

What you seem to want can be done by LINQ:

var lists = new List<List<int>>()
{
    new List<int> { 1, 1, 1, 1, 1, 1, 1 },
    new List<int> { 2, 1, 1, 1, 1, 1, 1 },
    new List<int> { 3, 1, 1, 1, 1, 1, 1 }
};

var result = lists
    .SelectMany(i => i.Select((value, index) => new { value, index }), (list, value) => value)
    .GroupBy(tuple => tuple.index)
    .Select(grouping => grouping.Select(tuple => tuple.value).Distinct().ToList()).ToList();

First we transform every value into an object containing the value and it's index (Select) then we flatten this list so we get one huge list with all entries (SelectMany). After that we group those by their indexes (GroupBy) and from these groupings we select the values (Select), on this we make sure all duplicates are removed (Distinct) and all these distinct values are put in a list (ToList) and all these lists are then put in the result list (ToList)