Как выполнить FindAll () для IList <T>? (например, SortedList.Values) - PullRequest
1 голос
/ 06 марта 2009

Я работаю над проблемой в C # 2.0 / .NET 2.0, где у меня есть Sortedlist, и я хочу найти все «значения» (не «ключи») этого SortedList для определенной подстроки и подсчитать, сколько вхождения есть.

Вот что я пытаюсь сделать:

{
   Sortedlist<string,string> mySortedList;
   // some code that instantiates mySortedList and populates it with data
   List<string> myValues = mySortedList.Values;  // <== does not work
   int namesFound = myValues.FindAll(ByName(someName)).Count;
}

Естественно, это не работает, потому что mySortedList.Values ​​возвращает IList, а myValues ​​- это List. Я попытался «привести» IList, чтобы он был принят myValues, но, похоже, он не работает.

Конечно, я могу перебирать mySortedList.Values ​​в цикле "foreach", но я не хочу этого делать.

У кого-нибудь есть предложения?

РЕДАКТИРОВАТЬ-1: Хорошо, похоже, нет простого способа сделать это легко. Я предполагал, что просто что-то упустил, но, по-видимому, я не так. Так что, думаю, я просто собираюсь сделать «foreach» над IList.

Спасибо всем за отзывы! Я проголосовал за всех 1, потому что я думал, что все отзывы были хорошими. Еще раз спасибо! : -)

РЕДАКТИРОВАТЬ-2: Похоже, CMS имеет ответ, который я искал. Единственное предостережение с этим (как указал Qwertie) заключается в том, что существует потенциальное снижение производительности, поскольку оно включает в себя копирование всех значений в другой список, а затем поиск в этом списке от начала до конца. Так что для коротких списков этот ответ эффективен. Более длинные списки? ну, это решать тебе ...

Ответы [ 5 ]

2 голосов
/ 06 марта 2009

Поскольку Интерфейс IList реализует IEnumerable , вы можете получить List<T> значений, используя List<T> (IEnumerable) Constructor:

List<string> myValues = new List<string>(mySortedList.Values);
2 голосов
/ 06 марта 2009

Нельзя преобразовать свойство Values ​​в List , поскольку это не список - это словарь .ValueCollection.

Но если вы используете LinqBridge (для .NET Framework 2.0 с C # 3.0), эта проблема легко решается с помощью LINQ следующим образом:

SortedList<string, string> m = ...;
int namesFound = m.Values.Where(v => v.Contains("substring")).Count();

(если вы все еще на C # 2.0, вы можете вместо этого использовать LINQ для бедняков, с немного большей работой)

1 голос
/ 06 марта 2009
    static void Main(string[] args)
    {
        string someName = "two";
        SortedList<string, string> mySortedList = new SortedList<string,string>()
        {
            {"key1", "This is key one"},
            {"key2", "This is key two"},
            {"key3", "This is key three"},
        };

        int namesFound = mySortedList.Values.Where(i => i.Contains(someName)).Count();
        Console.WriteLine(namesFound);
        Console.ReadKey();
    }

В Framework 2.0, возможно, может сделать это:

    static void Main(string[] args)
    {
        string someName = "two";
        SortedList<string, string> mySortedList = new SortedList<string,string>()
        {
            {"key1", "This is key one"},
            {"key2", "This is key two"},
            {"key3", "This is key three"},
        };

        int namesFound = FindAll(mySortedList.Values, someName).Count ;
        Console.WriteLine(namesFound);
        Console.ReadKey();
    }
    public static IList<String> FindAll(IList<String> items, string item)
    {
        List<String> result = new List<string>();
        foreach (String s in items)
        {
            if (s.Contains(item))
            {
                result.Add(s);
            }
        }
        return result;
    }

Но это то, что вы действительно не хотели делать.

1 голос
/ 06 марта 2009

Вы уже пробовали SortedList GetValueList? Это вернет вам IList значений.

1 голос
/ 06 марта 2009

Жаль, что вы в .Net 2.0. Это именно то, для чего предназначен LINQ. ;)

Вы не можете этого сделать, поскольку FindAll () является членом List. Вы можете создать новый List в mySortedList.Values, но это кажется пустой тратой, поскольку новый объект и базовый массив нужно размещать просто для вызова функции.

Я бы просто написал вспомогательную функцию в некотором классе для списков с именем FindAll (), а затем передал бы ваш IList и делегат.

...