Использование SortedDictionary TakeWhile возвращает пустой - PullRequest
2 голосов
/ 14 февраля 2011

Метод расширения TakeWhile содержит следующий комментарий во всплывающей подсказке: «Индекс элемента используется в логике функции предиката». Обратите внимание, что эта всплывающая подсказка не видна в обычной всплывающей подсказке, а только во всплывающей подсказке списка intellisense для списков членов переменной sortedDictionary.

Это именно то, что искали в сочетании с SortedDictionary.

var first = sortedDictionary.First(kv => kv.Key.ToString().StartsWith(searchkey));
var last= sortedDictionary.Last(kv => kv.Key.ToString().StartsWith(searchkey));
var range = sortedDictionary.TakeWhile(kv => kv.Key.ToString().StartsWith(searchkey));

Предметы, первые и последние, найдены и исправлены, однако диапазон моей коллекции пуст.
Что здесь не так? Я ожидал диапазон со всеми предметами между первым и последним, включая их.

Я все еще могу найти диапазон, используя первый и последний, но TakeWhile использует индекс, в то время как First и Last явно нет.

РЕДАКТИРОВАТЬ: «использование индекса» оказывается не имеет ничего общего с сортировкой, но вы можете использовать индекс в запросе. Например. когда я заменяю SortedDictionary на SortedList, я могу сделать:

int ix1 = sortedList.IndexOfKey(first.Key);
int ix2 = sortedList.IndexOfKey(last.Key);
var range = sortedList.SkipWhile((x, i) => i < ix1).TakeWhile((x, i) => i <= ix2);

Также с SortedDictionary я могу сделать:

var range = sortedList.SkipWhile(x => !x.Key.ToString().StartsWith(searchkey))
                      .TakeWhile(x => x.Key.ToString().StartsWith(searchkey));

Мне нужно проверить, какой метод быстрее, а также проверить запрос Where.

Ответы [ 3 ]

1 голос
/ 14 февраля 2011

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

Просто отфильтруйте элементы как обычно, и это должно привести к ожидаемому диапазону (из-зана сортировку).

var range = sortedDictionary.Where(kv => kv.Key.ToString().StartsWith(searchkey));
1 голос
/ 14 февраля 2011

Если первый элемент в вашей последовательности не соответствует вашему предикату, то метод TakeWhile завершится:

Возвращает элементы из последовательности как Пока указанное условие истинно

Метод First примет первый элемент, соответствующий вашему предикату:

Возвращает первый элемент в последовательность, которая удовлетворяет указанному состояние

В противоположность методу First метод Last будет принимать последний элемент, соответствующий вашему предикату:

Возвращает последний элемент последовательности которая удовлетворяет указанному условию

Я предполагаю, что TakeWhile завершается рано, потому что их элементов нет, соответствующих условию, когда начинается итерация.

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

var range = sortedDictionary.SkipWhile( x => !x.Equals( first ) )
  .TakeWhile( x => !x.Equals( last ) )
  .Concat( new SortedDictionary<string, string> { { last.Key, last.Value } } );

Или вы можете просто не задумываться над этим, как я, и использовать более простой подход, используя Where метод, как в примере Джеффа .

0 голосов
/ 14 февраля 2011

Прочитанная подсказка предназначена для перегрузки, предикат которой имеет Int32 в качестве параметра Ссылка MSDN

Не могли бы вы опубликовать некоторый код, чтобы понять, почему он возвращает пустой диапазон? Следующий код работает как положено (я копирую / вставляю ваш код).

        var sortedDictionary = new SortedDictionary<string, string>();
        var searchkey = "test";
        sortedDictionary.Add("test1", "value");
        sortedDictionary.Add("test2", "value");
        sortedDictionary.Add("test3", "value");
        sortedDictionary.Add("test4", "value");

        var first = sortedDictionary.First(kv => kv.Key.ToString().StartsWith(searchkey));
        var last = sortedDictionary.Last(kv => kv.Key.ToString().StartsWith(searchkey));
        var range = sortedDictionary.TakeWhile(
            kv => kv.Key.ToString().StartsWith(searchkey));
        foreach (var c in range)
        {
            Console.WriteLine(c);
        }
        Console.ReadKey();
...