Что лучший способ состоит в том, чтобы преобразовать неуниверсальный набор в универсальный набор?

Я преподавал мне LINQ недавно и применял его к различным небольшим загадкам. Однако одна из проблем, с которыми я столкнулся, - то, что LINQ к объектам только работает над универсальными наборами. Существует ли секретный прием / лучшая практика для преобразования неуниверсального набора к универсальному набору?

Моя текущая реализация копирует неуниверсальный набор в массив, затем воздействует на это, но я задавался вопросом, был ли лучший путь?

public static int maxSequence(string str)
{
    MatchCollection matches = Regex.Matches(str, "H+|T+");
    Match[] matchArr = new Match[matches.Count];
    matches.CopyTo(matchArr, 0);
    return matchArr
        .Select(match => match.Value.Length)
        .OrderByDescending(len => len)
        .First();
}
7
задан guhou 17 February 2010 в 07:05
поделиться

3 ответа

Самым простым способом обычно является метод расширения Cast -

IEnumerable<Match> strongMatches = matches.Cast<Match>();

Обратите внимание, что он является отложенным и передает свои данные потоком, поэтому у вас нет полноценной "коллекции" как таковой - но это совершенно прекрасный источник данных для LINQ-запросов.

Cast вызывается автоматически, если вы указываете тип переменной range в выражении запроса:

Так что для полного преобразования вашего запроса:

public static int MaxSequence(string str)
{      
    return (from Match match in Regex.Matches(str, "H+|T+")
            select match.Value.Length into matchLength
            orderby matchLength descending
            select matchLength).First();
}

или

public static int MaxSequence(string str)
{      
    MatchCollection matches = Regex.Matches(str, "H+|T+");
    return matches.Cast<Match>()
                  .Select(match => match.Value.Length)
                  .OrderByDescending(len => len)
                  .First();
}

На самом деле, вам не нужно вызывать OrderByDescending, а затем First здесь - вам просто нужно максимальное значение, которое вам дает метод Max. Еще лучше то, что он позволяет указать проекцию от типа исходного элемента к значению, которое вы пытаетесь найти, так что вы можете обойтись и без Select:

public static int MaxSequence(string str)
{      
    MatchCollection matches = Regex.Matches(str, "H+|T+");
    return matches.Cast<Match>()
                  .Max(match => match.Value.Length);
}

Если у вас есть коллекция, в которой есть некоторые элементы правильного типа, но есть и те, которые могут быть не правильными, вы можете использовать OfType вместо этого. Cast выбрасывает исключение, когда встречает элемент "неправильного" типа; OfType просто пропускает его.

10
ответ дан 6 December 2019 в 23:04
поделиться
matches.Cast<Match>();
0
ответ дан 6 December 2019 в 23:04
поделиться

Вы можете использовать Cast или OfType на IEnumerable для преобразования. Cast бросит ошибку приведения, если элемент не может быть приведен к указанному типу, а OfType пропустит все элементы, которые не могут быть преобразованы.

1
ответ дан 6 December 2019 в 23:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: