How ToLookup() with multiple indexes?

2019-06-25 15:53发布

Taking into account the code for C# Console application below, using

how should I modify it in order to substitute the line:

foreach (Product product in productsByCategory[category])

by the code line

foreach (Product product in productsByCategory[category][Id])

?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace myQuestion
{
  class Program
  {
    static void Main(string[] args)
    {
      var products = new List<Product>
      {
        new Product { Id = 1, Category = "Garden", Value = 15.0 },
        new Product { Id = 1, Category = "Garden", Value = 40.0 },
        new Product { Id = 3, Category = "Garden", Value = 210.3 },
        new Product { Id = 4, Category = "Pets", Value = 2.1 },
        new Product { Id = 5, Category = "Electronics", Value = 19.95 },
        new Product { Id = 6, Category = "Pets", Value = 21.25 },
        new Product { Id = 7, Category = "Pets", Value = 5.50 },
        new Product { Id = 8, Category = "Garden", Value = 13.0 },
        new Product { Id = 9, Category = "Automotive", Value = 10.0 },
        new Product { Id = 10, Category = "Electronics", Value = 250.0 }
      };


      ILookup<string, Product> productsByCategory = 
              products.ToLookup( p => p.Category);
      string category = "Garden";
      int Id = 1;
      foreach (Product product in productsByCategory[category])
      {
        Console.WriteLine("\t" + product);
      }

      Console.ReadLine();
    }
  }

  public sealed class Product
  {
    public int Id { get; set; }
    public string Category { get; set; }
    public double Value { get; set; }
    public override string ToString()
    {
      return string.Format("[{0}: {1} - {2}]", Id, Category, Value);
    }
  }
}

Update:
This is a contrived example with the aim of learning the concepts of C# ToLookup Method.

As a point of reference, I came to this question after reading the David Andres' answer to question "What is the point of Lookup?":

"A Lookup will map to potentially several values.  

Lookup["Smith"]["John"] will be a collection of size one billion."   

which I'd like to reproduce.

Or I understood it wrong?

2条回答
ら.Afraid
2楼-- · 2019-06-25 16:17

I've stumbled upon this question, read "closing it as being confirmed to me that it is impossible" and made a hefty research on the topic. The closest I could get to was this:

Striving to get a lookup of lookups

Turns out this can't be done because:

  1. There is no constructor for type Lookup<T, T>, one can only use .ToLookup() LINQ extension function,
  2. Said function doesn't have an overload with resultSelector (like .GroupBy() does) and thus always only returns IGrouping<TKey, TElement>.

Even if the result of the lookup is just one element (another Lookup), there is no possibility to omit the first IGrouping. So the call to .Single() (or .First() or .ToList()[0] or .ElementAt(0)) is required after each call to "parent" Lookup, which is... smelly and desperate.

But

The same syntax for accessing elements can be instead achieved with nested Dictionary<T, T>:

Got it with Dictionaries

LINQPad C# code uploaded here.

查看更多
迷人小祖宗
3楼-- · 2019-06-25 16:34

Not sure I understand your needs correctly, but why can't you just do:

foreach (Product product in productsByCategory[category].Where(x=> x.Id == Id))

Or with an anonymous object:

var productsByCategory = products.ToLookup(p => new { p.Category, p.Id });
string category = "Groceries";
int Id = 1;
foreach (Product product in productsByCategory[new {Category = category, Id= Id}])
{
    Console.WriteLine("\t" + product);
}

Here is very similar question with additional solution by Servy

查看更多
登录 后发表回答