2012-11-16 12 views
5

Vorrei sapere come posso ordinare gli elementi di una stringa [] in base a una posizione di stringa specifica. Per esempio voglio ordinare il seguente array dalla stringa "-"Ordinamento di un array di stringhe in base a una posizione di stringa (C#)

Ingresso: {xx - c, xxxxx - b, yyy - un, mlllll - d}

uscita prevista: {yyy - un, xxxxx - B, xx - c, mlllll - d}

quello che ho finora è la seguente:

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(); 
    } 
} 

qualcuno mi può cadere un suggerimento ...?

+0

Sembra che si desidera ordinare con la lettera che viene dopo '-', non dalla posizione di' -' che è la stessa in tutte le corde? – Esailija

+0

Quindi, quello che vuoi è la matrice di stringhe da ordinare, basata solo sull'ultima parte delle stringhe in essa contenute? Quindi ignorando i primi 4 caratteri, ad esempio? (O nel tuo caso, solo la parte dietro il "-"? " –

+0

OK scusate, non lo stavo specificando abbastanza chiaro.Voglio ordinare tutti gli elementi all'interno della stringa [] dove mai una determinata stringa X si verifica la prima volta Se X non esiste in un articolo Y, basta mettere Y alla fine della nuova stringa []. Spero che ora sia più chiaro ...? – oren

risposta

3

Per una performance e design migliore, vi consiglio utilizzare:

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; 
     } 

    } 

È possibile anche eliminare il metodo SortByStringPos e chiamare Array.Sort(arr, new MyStrComparer("-", ascending)); da qualsiasi punto del codice.

+0

hmmm ... il risultato di questo frammento non era giusto – oren

+0

@oren appena modificato. credo di adesso. – LMB

+0

System.ArgumentOutOfRangeException ... – oren

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

credo

quindi è necessario ordinare in modo consueto, quindi è possibile utilizzare questo, come orderBy .... ThenBy

+0

non funziona :-( – oren

+0

puoi spiegare più precisamente che cosa stai cercando di ottenere – 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

Quando una stringa X all'interno di un input non contiene il delimitatore, verrà persa ... male :-( – oren

+0

Caso risolto per i delimitatori mancanti :) – maximpa

+0

Grande, sembra essere la soluzione, grazie Maxim! – oren

0

Usa Substring per ottenere l'ultima parte della stringa. Le query LINQ possono essere costruite passo dopo passo. Questo riduce le ripetizioni di codice (= principio DRY, Do not Repeat Yourself):

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(); 
Problemi correlati