Секционированный список <T>? - PullRequest
3 голосов
/ 09 марта 2012

У меня есть большой список объектов, где мне иногда нужно перебирать весь список, а иногда я хочу посмотреть только на объекты, где .Property = "somevalue".

В настоящее время я просматриваю свою коллекцию .Where(_ => _.Property="value_i_need"), которая стоит дорого, если у меня загружено 100 тыс. Объектов, и в моей целевой группе только горстка.

Итак, я хотел бы сохранить список сегментированным, возможно, как Dictionary<string, List<T>>, чтобы я мог быстро ссылаться только на набор объектов, которые я хочу, но если я сделаю это, как можно перечислить всеобъекты во всех словарях, использующих Linq без использования дополнительной памяти для поддержания регулярного списка?

Ответы [ 4 ]

9 голосов
/ 09 марта 2012

Ну, звучит так, как будто вы хотите Lookup:

var lookup = list.ToLookup(x => x.Property);

Вы можете легко перебрать всю коллекцию, просто сгладив:

foreach (var entry in lookup.SelectMany(x => x))
{
}

... но это не будет в начальном порядке списка (если вам не очень повезет :). Если вам нужно сохранить исходный порядок списка, вам нужно будет проделать немного больше работы ...

1 голос
/ 09 марта 2012

Почему бы просто не упростить и сохранить эти конкретные объекты в другом списке?

0 голосов
/ 09 марта 2012

Вы можете иметь все объекты в одном списке, а также словарь индексов списка.

var list = new List<MyType>();

// Fill the list
...

// Create the index dictionary
var propIndexes = list
    .Select((obj, i) => new { obj.Property, i })
    .GroupBy(x => x.Property)
    .ToDictionary(g => g.Key,
                  g => g.Select(x => x.i).ToList());

// Iterate the objects having one specific property
foreach (int i in propIndexes["value_i_need"]) {
    Console.WriteLine(list[i]);
}
0 голосов
/ 09 марта 2012

Вот как вы можете сделать это с помощью словаря:

(например, Customer и CustomerStatus):

public class Customer
{
    public string Name
    {
        get;
        set;
    }

    public CustomerStatus Status
    {
        get;
        set;
    }
}

public enum CustomerStatus
{
    Pending = 0,
    Active = 1,
    Deleted = 2
}

// Create the dictionary based upon the "filters":
var dictionary = new Dictionary<CustomerStatus, ICollection<Customer>>();
dictionary.Add(CustomerStatus.Active, new List<Customer>());
dictionary.Add(CustomerStatus.Deleted, new List<Customer>());
dictionary.Add(CustomerStatus.Pending, new List<Customer>());

// Add some customers:
dictionary[CustomerStatus.Active].Add(new Customer
{
    Name = "Active 1"
});
dictionary[CustomerStatus.Active].Add(new Customer
{
    Name = "Active 2"
});
dictionary[CustomerStatus.Deleted].Add(new Customer
{
    Name = "Deleted"
});
dictionary[CustomerStatus.Pending].Add(new Customer
{
    Name = "Pending"
});

// Enumerate specific filter or all.
System.Console.WriteLine("Active Customers Only");
foreach (var customer in dictionary[CustomerStatus.Active])
{
    System.Console.WriteLine(customer.Name);
}

System.Console.WriteLine("---");

var allCustomers = dictionary.SelectMany(x => x.Value);

System.Console.WriteLine("All Customers");
foreach (var customer in allCustomers)
{
    System.Console.WriteLine(customer.Name);
}
...