2011-12-16 18 views
5

Ho un elenco di stringhe che contiene mesi dell'anno. Devo essere in grado di ordinare questo elenco in modo che i mesi siano in ordine per mese, non in ordine alfabetico. Ho cercato per un po 'ma non riesco a vedere per avvolgere la mia mente su nessuna delle soluzioni che ho trovato.Ordinamento dei mesi in un elenco

Ecco un esempio di come potrebbero essere aggiunti i mesi. Vengono aggiunti dinamicamente fuori dai campi in un elenco di SharePoint in modo che possano essere in qualsiasi ordine e possono avere duplicati (li rimuovo con Distinct()).

List<string> monthList = new List<string>(); 
monthList.Add("June"); 
monthList.Add("February"); 
monthList.Add("August"); 

auspica che riordinare questo:

February 
June 
August 
+0

perché non si registra di nuovo l'indice mese o numero? –

+0

Quali soluzioni hai trovato? Quale parte di quelle soluzioni era difficile da capire? – phoog

+0

Anche se ho bisogno che i miei nomi dei mesi siano in rumeno, questo mi aiuta molto e ora so come gestire il mio problema! Grazie! – Victor

risposta

5

È possibile analizzare la stringa in un DateTime e quindi ordinare utilizzando la proprietà di intero del mese. Vedi qui per i nomi dei mesi supportati: http://msdn.microsoft.com/en-us/library/system.globalization.datetimeformatinfo.monthnames.aspx

Qualcosa di simile a questo:

var sortedMonths = monthList 
    .Select(x => new { Name = x, Sort = DateTime.ParseExact(x, "MMMM", CultureInfo.InvariantCulture) }) 
    .OrderBy(x => x.Sort.Month) 
    .Select(x => x.Name) 
    .ToArray(); 
+0

+1 per sostituire i nomi dei mesi con le impostazioni di cultura – dthorpe

+0

Questo in realtà ha funzionato come un campione per me. Ti dispiacerebbe spiegare come funziona? Questa è una delle soluzioni che avevo colpito prima, ma non riuscivo a capire che cosa stessero facendo ognuno di quei metodi. – Mike

+0

Il primo 'Select' funzionerà su ogni elemento in' monthList', dove creerà un nuovo tipo anonimo con due proprietà: 'Name' e' Sort', dove 'Name' è la stringa originale, ad es. "Gennaio" e "Sort" è la stringa analizzata come "DateTime". "OrderBy' può quindi ordinare la sequenza, e infine la sequenza viene proiettata nella sua forma originale dei soli nomi del mese. Spero che abbia avuto senso! – lbergnehr

2

è possibile utilizzare un Dictionary<int,string> invece, utilizzare il int come un mese il numero per l'ordinamento, quindi l'ordinamento per tasto.

IDictionary<int,string> monthList = new Dictionary<int,string>(); 
monthList.Add(6, "June"); 
monthList.Add(2, "February"); 
monthList.Add(8, "August"); 

var sorted = monthList.OrderBy(item => item.Key); 
+0

C'è un motivo per cui lo si dovrebbe fare usando un ordinamento personalizzato rispetto a quello fornito da 'DateTime' (dopo l'analisi)? – lbergnehr

+0

@seldon - Non proprio. Estendendo semplicemente ciò che l'OP stava presentando. A seconda delle esigenze, questo potrebbe essere tutto ciò di cui ha bisogno - se ha bisogno di una lista ordinata sensibile alla cultura (e contiene tutti i mesi), questa è una cosa diversa. – Oded

0

Creare un enum e assegnare int valori per ogni mese. Ordina quella cosa con linq.

1

Se si insiste per avere una lista di soli archi che rappresentano mesi, quindi è necessario utilizzare un'altra origine dati per recuperare l'indice del mese con cui è possibile ordinare l'elenco. Ad esempio, è possibile popolare un dizionario con i nomi dei mesi come chiavi string e un indice int come valore. È quindi possibile utilizzare il metodo sovraccarico List<T>.Sort(Comparison<T>) e passare una funzione di confronto che restituisce l'indice dei mesi per nome (passandoli nel dizionario).

Tuttavia, suggerirei di non utilizzare una stringa raw in primo luogo, ma piuttosto un tipo di dati più strutturato che rappresenta un mese. È quindi possibile incorporare l'indice nella struttura dati stessa e ordinare in base a tale valore, offrendo così una soluzione più autonoma.

+0

No, non è necessaria un'altra origine dati per l'indice, almeno non se si fa affidamento sull'analisi della stringa del mese in un 'DateTime', che fornisce tutta la ricca struttura di dati di cui si parla. – lbergnehr

+0

@seldon: è necessario un altro codice di ordinamento se si ha a che fare con stringhe non elaborate come lo era il codice nella domanda originale. Potrebbe essere un 'DateTime' come menzioni o un indice' int' separato o qualunque cosa sia appropriata. – bobbymcr

+0

Ah, sì, hai ragione. Ci stavo pensando più in termini di definizione di quella chiave da soli o meno. – lbergnehr

1

Hai bisogno di un SortedList <> .. come

SortedList<int,string> monthList=new SortedList<int,string>(); 
monthList.Add(6,"June"); 
monthList.Add(2,"February"); 
monthList.Add(8,"August"); 
IList<string> sortedMonthList=monthList.Values; 

quindi utilizzare sortedMonthList per il resto.

Questo potrebbe essere migliorata utilizzando la risposta di Seldon creare una funzione, proprio come

public static int MonthNumFromName(String monthname) 
{ ... } 

e quindi utilizzare

monthList.Add(MonthNumFromName("June"),"June"); 

sopra.

+0

Sembra che @Oded mi abbia battuto con un approccio leggermente diverso –

0

Beh, immagino che non ci siano tecniche di ordinamento per questo con il mese puro come stringa.

È possibile utilizzare solo uno Dictionary<int, string> e utilizzare l'int per ordinare i mesi.

Se non ho sbagliato, in realtà stai avendo un elenco di mesi come stringa, quindi perché non lo fai?

List<string> months = new List<string> { "January", "February", ..., "December" }; 

var yourSortedMonthsInYourOriginalList = months.Where(m => 
               originalList.Any(o => o == m)).ToList(); 
0

È possibile costruire la propria classe sorta:

static void Main(string[] args) 
    { 
     List<string> monthList = new List<string>(); 
     monthList.Add("June"); 
     monthList.Add("February"); 
     monthList.Add("August"); 

     monthList.Sort(new _mysort()); 

    } 

    private class _mysort : IComparer<string> 
    { 

     public int Compare(string x, string y) 
     { 
      if (x=="February" && y=="June") 
      { 
       return -1; 
      } 

      return 0; 
     } 
    } 

Ma penso che si dovrebbe utilizzare un Enum, e convertirlo in stringa, quindi è possibile utilizzare il valore numerico per ordinarla.

enum months 
    { 
     Jan =0, 
     Feb =1 
    } 

come:

 List<months> mlist = new List<months>() { months.Feb, months.Jan }; 
     //sort 
     mlist = mlist.OrderBy(e => (int)e).ToList(); 
     //print 
     mlist.ForEach(e => Console.WriteLine(e.ToString())); 
2

È possibile analizzare i nomi dei mesi in date (si presuppone l'anno in corso e del giorno 1):

monthList = monthList.OrderBy(s=> DateTime.ParseExact(s, "MMMM", new CultureInfo("en-US"))).ToList(); 
Problemi correlati