2016-05-24 2 views
-1

пытается выбрать максимальную цифру из списка строк:Выбор максимального числа из списка строк в LINQ?

int maxDigit = this.myList.Where(x=> x.Name.Any(Char.IsDigit)) 
       .Select(x => int.Parse(x.Name)).DefaultIfEmpty(0).Max(); 

Это int.Parse(x.Name), которая вызывает исключение, как это возвращает всю строку имени, например, 'myValue99', который, разумеется, не может быть разобран на int. Я просто хочу вернуть 99. Я не знаю, где цифры будут в строке, поэтому не может, например, взять последние два.

Мне нужен DefaultIfEmpty для случаев, когда строка не содержит числа.

+4

Что делать, если строка «55 штук 66», в чем должен состоять анализ 'int'? – juharr

+0

Хороший вопрос, но в этом случае мне не о чем беспокоиться. Только когда-либо будет моим материалом1, stuff99 и т. Д. – Hardgraf

+4

Список и части Linq не имеют значения. Те же правила применяются к одной строке. См. Например [Найти и извлечь номер из строки] (http://stackoverflow.com/questions/4734116/find-and-extract-a-number-from-a-string), [Сплит числовая часть из буквенно-цифровой строки используя C#] (http://stackoverflow.com/questions/19288312/split-numeric-part-from-alphanumeric-string-using-c-sharp), [Извлечь числа из строки, чтобы создать только цифру) (http://stackoverflow.com/questions/11002527/extract-numbers-from-string-to-create-digit-only-string) и так далее. – CodeCaster

ответ

3

вы должны только выбрать и разобрать символы значного из вашей строки

int maxDigit = this.myList.Where(x => x.Name.Any(Char.IsDigit)) 
    .Select(x => int.Parse(new string(x.Name.Where(Char.IsDigit).ToArray()))) 
    .DefaultIfEmpty(0).Max(); 
+0

Но теперь вы перебираете каждый символ каждой строки дважды. – CodeCaster

+1

@CodeCaster только над цифрами: p – fubo

-1

Вероятно, есть дождевик способ сделать это, но я бы просто сделать:

int tmp = 0; 
int maxDigit = this.myList.Where(x=> x.Name.Any(Char.IsDigit)) 
       .Select(x => 
(int.TryParse(x.Name,out tmp) ? int.Parse(x.Name) : 0)).Max(); 

Вы должны помнить, что Параметр будет выходить из строя, если он не может проанализировать значение, но TryParse просто даст вам ложь.

+1

'myValue99' содержит цифры, но не будет разбираться, а OP хочет его. – CodeCaster

+1

Также разбор строки дважды кажется плохим. Либо просто проанализируйте его, либо используйте выходные параметры «TryParse». – juharr

+0

Не уверен, что если оптимизация включена, это может потерять значение для «tmp». Понял, что это, по крайней мере, даст ему его результат. Это не изящно, но это сработает. – JoshK

4

Если вы хотите получить максимальное количество , а не максимальная цифры, все, что вам нужно, это функция для преобразования "stuff99" в 99. Тогда Linq часть становится детской игрой:

int maxNumber = myList.Max(ExtractNumberFromText); 

или, чтобы быть ближе к спецификации:

int maxNumber = myList 
     .Select(ExtractNumberFromText) 
     .DefaultIfEmpty(0) 
     .Max(); 

@Codecaster уже указал на несколько применимых ответов на этом сайте для второй части. Я принял простой. Нет проверки ошибок.

// the specs: Only ever going to be my stuff1, stuff99  
int ExtractNumberFromText(string text) 
{  
    Match m = Regex.Match(text, @"\d*");    
    return int.Parse(m.Groups[0].Value);  // exception for "abc" 
     // int.Parse("0" + m.Groups[0].Value); // use this for default to 0 
} 
0

Это может быть простым использованием Regex.

Вы заявили , так что вам нужно пролетом более одной цифры:

var maxNumber = myTestList.SelectMany(x => getAllNumnbersFromString(x.Name)).DefaultIfEmpty(0).Max(); 

static List<int> getAllNumnbersFromString(string str) 
{ 
    List<int> results = new List<int>(); 

    var matchesCollection = Regex.Matches(str, "[0-9]+"); 

    foreach (var numberMatch in matchesCollection) 
    { 
     results.Add(Convert.ToInt32(numberMatch.ToString())); 
    } 

    return results; 
} 

Одна цифра только проверить:

int maxNumber = myTestList.SelectMany(x => x.Name.ToCharArray().ToList()) 
          .Select(x => Char.IsDigit(x) ? (int)Char.GetNumericValue(x) : 0) 
          .DefaultIfEmpty(0).Max(); 
+0

'Char.GetNumericValue' возвращает double, поэтому для' maxNumber' будет 'double' вместо' int'. – juharr

+0

@juharr Это хороший пример того, где мы не должны использовать var, чтобы указать на это. – user3185569

0

Чтобы найти максимальную цифру (не номер) в каждой строке:

static void Main(string[] args) 
{ 
    List<string> strList = new List<string>() { "Value99", "46Text" }; 
    List<int> resultList = new List<int>(); 

    foreach (var str in strList) 
    { 
     char[] resultString = Regex.Match(str, @"\d+").Value.ToCharArray(); 
     int maxInt = resultString.Select(s => Int32.Parse(s.ToString())).Max(); 
     resultList.Add(maxInt); 
    } 
} 
0

Предполагая, что вход может содержать следующие категории:

  • null сек
  • Пустых строк
  • Строки только с буквенными символами
  • Строки со смешанными алфавитным и цифровыми символами
  • струн только числовым символы

Вы хотите ввести метод, который извлекает число, если таковые имеются, или возвращает осмысленное значение, если нет:

private static int? ParseStringContainingNumber(string input) 
{ 
    if (String.IsNullOrEmpty(input)) 
    { 
     return null; 
    } 

    var numbersInInput = new String(input.Where(Char.IsDigit).ToArray()); 
    if (String.IsNullOrEmpty(numbersInInput)) 
    { 
     return null; 
    } 

    int output; 

    if (!Int32.TryParse(numbersInInput, out output)) 
    { 
     return null; 
    } 

    return output; 
} 

Обратите внимание, что не все символы, для которых Char.IsDigit возвращает true могут быть разобраны Int32.Parse(), следовательно, в TryParse.

Затем вы можете подать свой список к этому методу:

var parsedInts = testData.Select(ParseStringContainingNumber) 
         .Where(i => i != null) 
         .ToList(); 

И делать все, что вы хотите с parsedInts списка, как вызов IEnumerable<T>.Max() на него.

со следующими данными испытания:

var testData = new List<string> 
{ 
    "۱‎", // Eastern Arabic one, of which Char.IsDigit returns true. 
    "123", 
    "abc456", 
    null, 
    "789xyz", 
    "foo", 
    "9bar9" 
}; 

Это возвращает:

123 
456 
789 
99 

Особенно обратите внимание на последний случай.