2016-08-18 2 views
1

У меня есть список numbers и number-letter и letter-number .Отель типа моего столбца строка .My данных, как это:Сортировать поле, содержащее цифры и буквы

1 
14 
3 
S-34 
2 
36-1/E 
26 
S-14 
20 
S-2 
19 
36-1 
30 
35 
S-1 
34 

, но я хочу, чтобы разобраться, как это:

1 
2 
3 
14 
20 
25 
30 
35 
36-1 
36-1/E 
S-1 
S-2 
S-14 
S-34 

Но мой код сортировать данные, как это:

1 
14 
19 
2 
20 
25 
3 
30 
35 
36-1 
36-1/E 
S-1 
S-14 
S-2 
S-34 

мой код:

List<ViewTestPackageHistorySheet> lstTestPackageHistorySheets = _reportTestPackageHistorySheetRepository.ShowReport(Id).OrderBy(i => i.JointNumber).ToList(); 

Я изменил код ниже, но не смог.

List<ViewTestPackageHistorySheet> lstTestPackageHistorySheets = _reportTestPackageHistorySheetRepository.ShowReport(Id).OrderBy(i => Convert.ToInt32(i.JointNumber)).ToList(); 

Ошибка:

LINQ to Entities does not recognize the method 'Int32 ToInt32(System.String)' method, and this method cannot be translated into a store expression. 
+0

вниз голосование, пожалуйста, комментарий –

+0

Пользовательские Буквенно сортировщик, который проверяет, является ли два элемента число затем сравнить значения остальное сделать сравнение строк, вуаля, и вы получите требуемый выходной –

+0

HTTP: //stackoverflow.com/questions/2619617/how-to-sort-number-in-alphanumeric – sharno

ответ

1

Используйте следующие Alphanumericsorter, которые используют PInvoke внутренне

public class AlphaNumericSorter : IComparer<string> 
{ 
    public int Compare(string x, string y) 
    { 
     return SafeNativeMethods.StrCmpLogicalW(x, y); 
    } 
} 

[SuppressUnmanagedCodeSecurity] 
internal static class SafeNativeMethods 
{ 
    [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] 
    public static extern int StrCmpLogicalW(string psz1, string psz2); 
} 

Использование:

List<string> testList = // Your input list; 

testList.Sort(new AlphaNumericSorter()); 

Теперь testList содержит отсортированные данные, е xpected в вопросе

1

Создание пользовательских Comparer<string> и реализовать требуемую логику (Конечно, это неэффективно для больших списков, и вы должны настроить его):

var data = list.OrderBy(x => x, new SpecialComparer()); 

SpecialComparer

public class SpecialComparer : IComparer<string> 
     { 
      public int Compare(string x, string y) 
      { 
       if (x.Equals(y)) 
        return 0; 

       int yn; 
       int xn; 
       bool isXNumber = int.TryParse(x, out xn); 
       bool isYNumber = int.TryParse(y, out yn); 

       if (isXNumber && isYNumber) 
       { 
        return xn.CompareTo(yn); 
       } 
       else if (isXNumber && !isYNumber) 
       { 
        return -1; 
       } 
       else if (!isXNumber && isYNumber) 
       { 
        return 1; 
       } 
       else if(x.Any(c => c == '/' || c == '-') || y.Any(c => c == '/' || c == '-')) 
       { 
        var xParts = x.Split("/-".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); 
        var yParts = y.Split("/-".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); 

        var minLen = Math.Min(xParts.Length, yParts.Length); 

        var result = 0; 
        for (int i = 0; i < minLen; i++) 
         if ((result = Compare(xParts[i], yParts[i])) != 0) 
          return result; 

        return x.Length < y.Length ? -1 : 1; 
       } 
       else 
       { 
        return x.CompareTo(y); 
       } 
      } 
     } 
+0

Я получаю эту ошибку: Уровень опасности \t Код \t Описание \t P РОЕКТ \t \t File Line Ошибка \t \t CS0411 Аргументы типа для метода 'Enumerable.OrderBy (IEnumerable , Func , IComparer )' не может быть выведено из эксплуатации. Попробуйте явно указать аргументы типа –

+0

вот мой код: _reportTestPackageHistorySheetRepository.ShowReport (Id) .ToList().OrderBy (x => x, новый SpecialComparer()); –

+0

Возьмите этот список - '' 1017 "," 650 "," 650C "," 650B "," W323 "," 10 "," 20 "," 1000 "," W1000 "," W900 "', решение выше, не работает для элементов, начинающихся с алфавита, это приведет к «W323, W900, W1000», но результат решения - «W1000, W323, W900», поскольку мы не сравниваем каждый символ –

1

Linq для Entities не поддерживает Convert.ToInt32, это то, что вызывает ошибку в вашем случае, я бы предложил материализовать запрос, а затем применить упорядоченность.

List<ViewTestPackageHistorySheet> lstTestPackageHistorySheets = _reportTestPackageHistorySheetRepository.ShowReport(Id).ToList(); 

// Now order the list. 
lstTestPackageHistorySheets = lstTestPackageHistorySheets.Select(x=> 
      new 
      { // split number and string 
       number = Regex.IsMatch(x.Split('-')[0],@"^\d+$")? int.Parse(x.Split('-')[0]): int.MaxValue, 
       item =x 
      }) 
    .OrderBy(x=>x.number) // first order by number 
    .ThenBy(x=>x.item)  // then order by string. 
    .Select(x=>x.item) 
    .ToList(); 

Проверить это Demo

+0

Возьмите этот список - '' 1017 "," 650 "," 650C "," 650B "," W323 "," 10 "," 20 "," 1000 "," W1000 "," W900 ", решение, вышеописанное, не работает для элементов, начинающихся с Alphabet, оно должно приводить к' W323, W900, W1000', но результатом решения является 'W1000, W323, W900', так как мы не сравниваем каждого персонажа. –

+0

Ahh ... вы должны объяснить, что в вопросе, основываясь на вашем примере, я думал, что существует разделитель, если он начинается с числа, но помните, что идея такая же. Вам просто нужно извлечь номер, если он начинается с номера. –

+0

Я не ОП :), тем не менее, вы можете исправить ответ –

Смежные вопросы