2016-12-11 6 views
0

文字列の並べ替えに対応してください。C#LINQ条件付き整数のOrderBy文字列

私は、Oracleデータベースのselect文の結果を含むListを持っています。一般的には、次のようになります。

"9", 
"10 k. 1 str. 1", 
"10 k. 2 str. 1", 
"11 k.1", 
"12", 
"12 k.1 str. 2" 

しかし、もちろんそうではありません。

私は、次のようなLINQクエリを使用して、それを並べ替えることができます。

var oLst = lst.OrderBy(x => int.Parse(x.Split(' ')[0])).ToList(); 

そしてそれは、このリストをソートするが、唯一の最初の整数で。私がしたいのは、x.Split(' ')[2]という文字列要素の存在に基づいて、ある種の「条件付きThenBy()」ソートですが、どうやってそれを行うのか分かりません。私が望むのは、最初に文字列の "最初の"整数でソートし、それが存在すれば2番目のものから3番目のものまで並べ替えることです。

var oLst = lst.OrderBy(x => int.Parse(x.Split(' ')[0])).ThenBy(x => int.Parse(x.Split(' ')[2])).ThenBy(x => int.Parse(x.Split(' ').Last())).ToList(); 

整数値のすべてを持っている「完全な文字列」でのみ動作しますが、どのように私は、リストのいくつかの文字列で、このSplit(' ')[]要素の非existanceと状況を管理することができますか?

答えて

1

あなたは比較演算を実現することができます。

public class NumberExtractorComparer : IComparer<MatchCollection> 
{ 
    private static readonly Regex rx = new Regex("[0-9]+"); 

    public static readonly NumberExtractorComparer Comparer = new NumberExtractorComparer(); 

    // Returns a MatchCollection composed of all the groups of 
    // digits 
    public static MatchCollection Selector(string str) 
    { 
     return rx.Matches(str); 
    } 

    // Compares two matchcollections 
    public int Compare(MatchCollection x, MatchCollection y) 
    { 
     int min = Math.Min(x.Count, y.Count); 

     for (int i = 0; i < min; i++) 
     { 
      // Using long to support bigger numbers 
      long l1 = long.Parse(x[i].Value); 
      long l2 = long.Parse(y[i].Value); 

      int cmp = l1.CompareTo(l2); 

      if (cmp != 0) 
      { 
       return cmp; 
      } 
     } 

     return x.Count.CompareTo(y.Count); 
    } 
} 

、次に

私は比較( NumberExtractorComparer.Comparer)を行う前に数字( NumberExtractorComparer.Selector)を抽出しています
var res = lst 
    .OrderBy(
     NumberExtractorComparer.Selector, 
     NumberExtractorComparer.Comparer) 
    .ToArray(); 

注意。このように、数字は、コレクションの各要素に対して一度だけ抽出されます(数字抽出は比較部に比べて、おそらくかなり遅いです)

+0

魅力のように働く、たくさんのthanx! –

0

文字列から数値を抽出し、数値の値でソートすることができます。

var oLst = lst.OrderBy(x => int.Parse(Regex.Replace(x, "[^0-9]", ""))).ToList(); 
+0

私は期待通りに動作していません –

+0

私は申し訳ありませんテストを行ってください – ArDumez

0

文字列をdoubleに変換し、そのdoubleでソートすることができます。たとえば:

"9" => 9.0 
"10 k. 1 str. 1" => 10.11 
"10 k. 2 str. 1" => 10.21 
"11 k.1" => 11.0 
"12" => 12.0 
"12 k.1 str. 2 => 12.2 

トリックを行います方法は次のとおりです。

Parse(string str) 
     { 
      double res = 0; 
      string[] p = str.Split(' '); 

      double multuplier = 1.0; 

      p.ToList().ForEach(f => 
      { 
       int parsed; 
       if(int.TryParse(f, out parsed)) 
       { 
        res += parsed * multuplier; 
        multuplier *= 0.1; 
       } 
      }); 

      return res; 
     } 

してからちょうど使用:

List<string> ordered = lst.OrderBy(Parse).ToList(); 
0
var query = from x in source 
    let tokens = x.Split(' ') 
    order by 
    GentlyParse(tokens.FirstOrDefault()), 
    GentlyParse(tokens.Skip(2).FirstOrDefault()), 
    GentlyParse(tokens.LastOrDefault()) 
    select x; 

var results = query.ToList(); 

GentlyParseは、あなたがとる書く必要があります方法であり、文字列(またはnull)を返し、解析できるintまたはnullを返します。