2013-02-24 3 views
3

Я создаю систему оценки, которая читает/записывает в текстовый файл. Мой текущий формат читает каждую строку файла и сохраняет каждую строку в List<string>. Типичная строка будет примерно 50:James (50 being the score, James being the username).C# Сортировка списка строк, содержащих числа

Мне нужно заказать список по счету, сохранив имя со строкой. Вот пример того, что я имею в виду:

Unordered текстовый файл:

50:James 
23:Jessica 
70:Ricky 
70:Dodger 
50:Eric 

(Обратите внимание, есть некоторые оценки, которые являются такими же, что затрудняет мое использование создания списка с помощью цифровых клавиш)

Упорядоченный список:

70:Dodger 
70:Ricky 
50:Eric 
50:James 
23:Jessica 

Мой текущий код (который не работает с двумя или более одинаковых баллов)

Dictionary<int, string> scoreLines = new Dictionary<int, string>(); 

if (!File.Exists(scorePath)) 
{ 
    File.WriteAllText(scorePath, "No Scores", System.Text.Encoding.ASCII); 
} 

StreamReader streamReader = new StreamReader(resourcePath + "\\scoreboard.txt"); 

int failedLines = 0; 

while (failedLines < 3) 
{ 
    string line = streamReader.ReadLine(); 

    if (String.IsNullOrEmpty(line)) 
    { 
     failedLines++; 
     continue; 
    } 

    scoreLines.Add(int.Parse(line.Split(':')[0]), line.Split(':')[1]); 
} 

var arr = scoreLines.Keys.ToArray(); 
arr = (from a in arr orderby a descending select a).ToArray(); 

List<string> sortedScoreLines = new List<string>(); 

foreach (int keyNum in arr) 
{ 
    sortedScoreLines.Add(keyNum + ":" + scoreLines[keyNum]); 
} 

return sortedScoreLines; 

Да, я знаю, что это TERRIBLY неэффективно и уродливо, но я потратил века, пытаясь использовать множество разных методов.

ответ

9

Вы можете использовать String.Split:

var ordered = list.Select(s => new { Str = s, Split = s.Split(':') }) 
      .OrderByDescending(x => int.Parse(x.Split[0])) 
      .ThenBy(x => x.Split[1]) 
      .Select(x => x.Str) 
      .ToList(); 

Редактировать: Вот демо с вашими данными на Ideone: http://ideone.com/gtRYO7

+0

+1, опередил меня :) – Bort

+1

Попробуйте добавить объяснение того, что происходит. Я очень сомневаюсь, что ОП понимает этот код. – evanmcdonnal

+0

Он работал безупречно, спасибо большое! По общему признанию, я этого не понимаю, но я сделаю немного исследований! –

3

Вы можете использовать метод ReadAllLines легко прочитать файл, а затем OrderByDescending сортировать строки по значениям, которые вы анализируете из них:

string[] sortedScoreLines = 
    File.ReadAllLines(resourcePath + "\\scoreboard.txt") 
    .OrderByDescending(s => Int32.Parse(s.Substring(0, s.IndexOf(':')))) 
    .ThenBy(s => s) 
    .ToArray(); 
0

Проверьте это:

var sortedScoreLines = GetLines("inputFilePath") 
     .Select(p => new { num = int.Parse(p.Split(':')[0]), name = p.Split(':')[1] }) 
     .OrderBy(p => p.num) 
     .ThenBy(p => p.name) 
     .Select(p => string.Format("{0}:{1}", p.num, p.name)) 
     .ToList(); 

    private static List<string> GetLines(string inputFile) 
    { 
     string filePath = Path.Combine(Directory.GetCurrentDirectory(), inputFile); 
     return File.ReadLines(filePath).ToList(); 
    } 
1

На основании ответа Guffa с еще несколько замечаний

string[] sortedScoreLines = 
      File.ReadAllLines(resourcePath + "\\scoreboard.txt"); 

     // parse into an anonymous class 
     var parsedPersons = from s in sortedScoreLines 
          select new 
             { 
              Score = int.Parse(s.Split(':')[0]), 
              Name = s.Split(':')[1] 
             }; 

     // sort the list 
     var sortedPersons = parsedPersons.OrderByDescending(o => o.Score).ThenBy(i => i.Name); 

     // rebuild the resulting array 
     var result = (from s in sortedPersons 
        select s.Score + ":" + s.Name).ToArray(); 
Смежные вопросы