开发者

C# LINQ Autogenerated number or index

When deriving combination,what is the possible way to generate auto generate numbers.

public enum Color
{
    Red,Green,Blue
}

public enum Vehicle
{
    Car,Bike
}

(i.e) {Red,Car},{Red,Bike},{Green,Car},{Green,Bike}......

(Jon Skeet helped me t开发者_JAVA百科o solve it).

var query = from Color c in Enum.GetValues(typeof(Color))
            from Vehicle v in Enum.GetValues(typeof(Vehicle))
            select new { Color = c, Vehicle = v };

Now I want the combination like this

{1,Red,Car},{2,Red,Bike},{3,Green,Car},{4,Green,Bike},{5,Blue,Car},{6,Blue,Bike}

What is the way to generate auto numbers?


Another option is to use the overloaded Select method that includes an item's index. Building on your original query, you could use this:

var indexedQuery = query.Select((item, i) => new { Index = i + 1, Item = item });
foreach (var o in indexedQuery)
{
   Console.WriteLine("{0},{1},{2}", o.Index, o.Item.Color, o.Item.Vehicle);
}


Try:

int optionNumber = 0;
var query = from Color c in Enum.GetValues(typeof(Color))
            from Vehicle v in Enum.GetValues(typeof(Vehicle))
            select new { Number = optionNumber++, Color = c, Vehicle = v };


Solution #1: I believe this is the most efficient LINQ-Like solution. It uses the permutation count to enumerate efficiently; in reality, it can work for any Enum that doesn't change the default values (0,1,2,.. n)

int colorCount = Enum.GetValues(typeof(Color)).Length;
int vehicleCount = Enum.GetValues(typeof(Vehicle)).Length;
var permutations = Enumerable
                   .Range(0, colorCount * vehicleCount)
                    .Select (index => 
                               new {
                                     Index = index + 1,
                                     Color = (Color)(index / colorCount),
                                     Vehicle = (Vehicle)(index % vehicleCount)
                                   });

Solution #2: This one is in reality the most efficient solution, since it won't actually enumerate anything, giving you an O(1) solution, but it has an ugly hack there that does (T)(object)(int). Use at your risk.

class Permutations<T1, T2> : IEnumerable<Tuple<int, T1, T2>>
    where T1 : struct
    where T2 : struct
{
    int countT1 = 0;
    int countT2 = 0;

    public Permutations()
    {
        countT1 = Enum.GetValues(typeof(T1)).Length;
        countT2 = Enum.GetValues(typeof(T2)).Length;        
    }

    public int Length
    {
        get {
            return countT1 * countT2;
        }
    }

    public Tuple<int, T1, T2> this[int index]
    {
        get {
            Contract.Requires(index >= 1, "Index is out of lower bounds: Options are 1 - N.");
            Contract.Requires(index <= Length, "Index is out of upper bound.");                 
            return new Tuple<int, T1, T2>(
                       index,
            /*Hack ->*/(T1)(object)((index - 1) / countT1),
            /*Hack ->*/(T2)(object)((index - 1) % countT2));
        }
    }

    public IEnumerator<Tuple<int, T1, T2>> GetEnumerator()
    {
        return Enumerable.Range(1, this.Length).Select (i => this[i]).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

void Main()
{       
    var permutations = new Permutations<Color, Vehicle>();
    // Can be accesed individually:
    var permutation = permutations[1];
    // Can be accesed using Enumerations
    permutations.Dump(); // LINQPad Dump
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜