2012-11-16 12 views
5

文字列[]の項目を特定の文字列の位置に従ってどのように並べ替えることができますか?例えば、iはサブストリングによって次の配列をソートする " - "文字列の位置(C#)に従って文字列配列を並べ替える

入力を:{XX - C、XXXXX - B、YYY - 、mlllll - D}

期待出力:{YYY - 、 xxxxxは - B、XX - C、mlllll - D}

私はこれまで、次のされているもの:

public string[] SortByStringPos(string[] arr, string str, bool ascending) 
{ 
    if (ascending) 
    { 
     var result = from s in arr 
        where s.Length >= s.IndexOf(str) 
        orderby s[s.IndexOf(str)] ascending 
        select s; 

     return result.ToArray(); 
    } 
    else 
    { 
     var result = from s in arr 
        where s.Length >= s.IndexOf(str) 
        orderby s[s.IndexOf(str)] descending 
        select s; 

     return result.ToArray(); 
    } 
} 

は、誰かが私にヒントをドロップすることができますか...?

+0

コードの繰り返しを減らす( 'DRY原則、あなた自身を繰り返さないでください)' -'の後に来る文字でソートしたいのですが、 '-'の位置ではなくすべての弦で? – Esailija

+0

それでは、文字列の最後の部分だけに基づいて、文字列配列をソートするのですか?たとえば最初の4文字は無視しますか? (またはあなたの場合、 " - "の後ろの部分だけ? " –

+0

申し訳ありませんが、私はそれを明確に指定していませんでした。 Xが項目Yに存在しない場合、新しい文字列[]の末尾にYを入れてください。 もっと明確になることを願っています...? – oren

答えて

3

はそうあなたは、あなたがORDERBYのように、これを使用することができ、通常の方法でそれを注文する必要があると思い、私はあなたをお勧めします使用:

public void SortByStringPos(string[] arr, string str, bool ascending) 
    { 
     Array.Sort(arr, new MyStrComparer("-", ascending)); 
    } 

    class MyStrComparer : Comparer<string> 
    { 
     string delimiter; 
     bool isAscending; 

     public MyStrComparer(string aStr, bool ascending) 
     { 
      delimiter = aStr; 
      isAscending = ascending; 
     } 

     public override int Compare(string x, string y) 
     { 
      var r = GetMySubstring(x).CompareTo(GetMySubstring(y)); 
      return isAscending ? r : -r; 
     } 

     string GetMySubstring(string str) 
     { 
      return str.IndexOf(delimiter) != -1 ? str.Substring(str.LastIndexOf(delimiter)) : string.Empty; 
     } 

    } 

ます。またSortByStringPosメソッドを削除し、どこでも、あなたのコード内からArray.Sort(arr, new MyStrComparer("-", ascending));を呼び出すことができます。

+0

hmmm ...このスニペットの結果は正しくありません – oren

+0

@oren今すぐだと思います – LMB

+0

System.ArgumentOutOfRangeException ... – oren

3
orderby x=>x.Substring(x.LastIndexOf('-')) 

私は....優れた性能とデザインのためにthenBy

+0

は動作しません:-( – oren

+0

あなたは説明できますかより具体的には何を達成しようとしています – m4ngl3r

2
static void Main() 
{ 
    var input = new[] { "xx - c", "xx - b", "yy - a", "ml - d", }; 
    var delimeter = "-"; 
    var isAscending = true; 

    var res = Sort(input, delimeter, isAscending); 
} 

static string[] Sort(string[] input, string delimeter, bool isAscending) 
{ 
    var withDelimeter = input.Where(p => p.Contains(delimeter)); 
    var withoutDelimeter = input.Except(withDelimeter); 

    Func<string, string> selector = p => p.Substring(p.IndexOf(delimeter)); 

    return 
     (
      isAscending 

       ? withDelimeter.OrderBy(selector) 
        .Concat(withoutDelimeter.OrderBy(p => p)) 

       : withoutDelimeter.OrderByDescending(p => p) 
        .Concat(withDelimeter.OrderByDescending(selector)) 
     ) 
     .ToArray(); 
} 
+0

入力内の文字列Xにデリミタが含まれていないと、それが失われてしまいます...悪い:-( – oren

+0

デリミタが見つからない場合の解決方法:) – maximpa

+0

偉大な解決策です。 – oren

0

文字列の最後の部分を取得するのに、Substringを使用してください。 LINQクエリは、段階的に構築できます。

var query = arr.Where(s => s.Contains(str)); 
Func<string,string> sortExpr = s => s.Substring(s.IndexOf(str)); 
if (ascending) { 
    query = query.OrderBy(sortExpr); 
} else { 
    query = query.OrderByDescending(sortExpr); 
} 
return query.ToArray(); 
関連する問題