2014-11-13 5 views
0

Я читал строки из файла, разделенного точкой с запятой, и я нашел здесь, как отсортировать список:уравновешивания при сортировке списка

IEnumerable<string> sSortedList = sList.Select(line => new 
{ 
    SortKey1 = line.Split(';')[4].Trim(), 
    SortKey2 = line.Split(';')[1].Trim(), 
    Line = line 

}) 
.OrderBy(Section => Section.SortKey1) 
.ThenBy(StdName => StdName.SortKey2) 
.Select(sResult => sResult.Line); 

я должен был использовать обшивку в sortkeys, потому что, если у меня нет, я не буду получить их отсортирован правильно ..

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

foreach (string sLine in sSortedList) 
{ 
    if (sLine.Contains("3")) 
    { 
     dataGridView1.InvokeEx(control => control.Rows.Add(sLine.Split(';').Select(sCol => sCol.Trim()).ToArray<string>())); 
     listBox1.InvokeEx(control => control.Items.Add("Processed Line: " + sLine)); 
    } 
} 

Я не хочу обрезать поля во время fil ling DataGridView, я просто хочу обрезать все поля при сортировке, возможно ли это?

+0

Вы возвращаетесь к вам отсортированный список всей линии, которые не являются подрезки. Я думаю, что вы не можете сделать это по-другому –

ответ

0

Первый магазин Ваши данные в более специализированном объекте:

internal class ProcessedLine 
{ 
    public string Original {get; private set;} 
    public string[] Trimmed {get; private set;} 

    public ProcessedLine(string original) 
    { 
     Original = original; 
     Trimmed = original.Split(';').Select(x => x.Trim()).ToArray(); 
    } 

    public string SortKey1 
    { 
     get{ return Trimmed[4]; } 
    } 

    public string SortKey2 
    { 
     get{ return Trimmed[1]; } 
    } 
} 

Затем вы можете использовать его как это:

var processedLines = sList.Select(x => new ProcessedLine(x)).ToList(); 

foreach (var processedLine in processedLines.OrderBy(x => x.SortKey1).ThenBy(x => x.SortKey2)) 
{ 
    if (lineObject.Original.Contains("3")) 
    { 
     dataGridView1.InvokeEx(control => control.Rows.Add(lineObject.Trimmed)); 
     listBox1.InvokeEx(control => control.Items.Add("Processed Line: " + lineObject.Original)); 
    } 
} 

Пожалуйста, обратите внимание, что я не рекомендовал бы это. (Кроме того, я не на 100% уверен, что он работает, не проверял его, но вы можете видеть, что представляют собой концепции.)

IMHO вам будет лучше, если вы сначала конвертируете свою линию в более значимый объект, например, используя FileHelpers. Сортировка по «четвертой части расщепленной строки» по существу бессмысленна и является неправильным кодом IMHO, поскольку для этого требуется, чтобы вы определяли формат входного файла; преобразование строки в объект со значением (например, первая часть - это идентификатор, третья часть - имя и т. д.) позволяет писать более значимый код.

BTW Microsoft doesn't like Hungarian notation WRT to C#: «s» в начале sList и sSortedList и т. Д. Кроме того, я советовал бы называть что-то «отсортированным списком», когда it isn't one.

+0

'Trimmed = original.Select (x => x.Split (';')). Выберите (x => x.Trim()). ToList()' производит следующая ошибка: «char» не содержит определения для «Split» – elekgeek

+0

Ах, да, да. Починил это. – BCdotWEB

+0

Спасибо, это сработало с одной модификацией: 'dataGridView1.InvokeEx (control => control.Rows.Add (обработанная .Trimmed.ToArray())); ' я должен был добавить ToArray(), в противном случае первый столбец заполнен: System.Collections.Generic.List1 [System.String] Во всяком случае, я действительно должен использовать ToList() в этой строке: 'var обрабатываетсяLines = sList.Select (x => new ProcessedLine (x)). ToList();' и почему? Кроме того, почему я должен использовать ToArray(), хотя в классе вы использовали ToList() в этой строке: 'Trimmed = Original.Split (';'). Выберите (x => x.Trim()). ToList(); ' – elekgeek

0

@BCdotNET Мне удалось изменить свой класс в соответствии с прошлыми комментариями и создать собственный класс, поскольку вы предложили максимально инкапсулировать весь процесс, я все еще думаю о том, как инкапсулировать имена полей csv, чтобы сделать его более общим, я все еще нужно больше идей:

internal class ProcessedLine 
    { 
     public string Original { get; private set; } 
     public string[] Trimmed { get; private set; } 

     public ProcessedLine(string original) 
     { 
      Original = original; 
      Trimmed = Original.Split(';').Select(x => x.Trim()).ToArray(); 
     } 

     public string SortKey1 
     { 
      get { return Trimmed[4]; } 
     } 

     public string SortKey2 
     { 
      get { return Trimmed[1]; } 
     } 

     public string JoinedTrimmed 
     { 
      get { return string.Join(";", Trimmed); } 
     } 
    } 

Вот мой класс:

internal class ReadAllLinesFromFilesInDirectory 
    { 
     private List<string> AllPlainLinesFromAllFiles = new List<string>(); 
     private List<string> SortedJoinedTrimmedAllLines = new List<string>(); 

     public ReadAllLinesFromFilesInDirectory(string directoryPath, string TopicName, string LinesToExclude) 
     { 
      string[] fileEntries = Directory.GetFiles(directoryPath, TopicName + "*", SearchOption.TopDirectoryOnly).Where(s => s.EndsWith(".csv", StringComparison.InvariantCultureIgnoreCase)).ToArray(); 
      foreach (string fileEntry in fileEntries) 
      { 
       List<string> ReadLinesFromFileToList = new List<string>(File.ReadAllLines(fileEntry, Encoding.Default) 
        .Where(x => !x.Contains(LinesToExclude)) 
        .ToList()); 
       for (int lineCount = 0; lineCount < ReadLinesFromFileToList.Count(); lineCount++) 
       { 
        ReadLinesFromFileToList[lineCount] = String.Format("{0};{1}", ReadLinesFromFileToList[lineCount], Path.GetFileNameWithoutExtension(fileEntry).Replace("-", string.Empty).ToUpper()); 
       } 
       AllPlainLinesFromAllFiles.AddRange(ReadLinesFromFileToList); 
      } 
     } 

     public List<string> SortedJoinedTrimmedAllLinesToList() 
     { 

      SortedJoinedTrimmedAllLines = AllPlainLinesFromAllFiles 
       .Select(x => new ProcessedLine(x)) 
       .OrderBy(x => x.SortKey1) 
       .ThenBy(x => x.SortKey2) 
       .Select(x => x.JoinedTrimmed) 
       .ToList(); 
      return SortedJoinedTrimmedAllLines; 
     } 

     public List<string> ToList() 
     { 
      return AllPlainLinesFromAllFiles; 
     } 
    } 

Я использую это так:

 this.InvokeEx(x => x.dataGridView1.ColumnCount = columnHeader.Split(';').Count<string>()); 
     List<string> AllLinesFromAllFilesToListTrimmedSorted = new ReadAllLinesFromFilesInDirectory("StudentList", "IT102-Cplus-Section", "StudentID").SortedJoinedTrimmedAllLinesToList(); 

     this.InvokeEx(x => x.toolStripProgressBar1.Value = 0); 
     this.InvokeEx(x => x.toolStripProgressBar1.Maximum = AllLinesFromAllFilesToListTrimmedSorted.Count()); 

     foreach (string singleLine in AllLinesFromAllFilesToListTrimmedSorted) 
     { 
      this.InvokeEx(x => x.toolStripProgressBar1.Value++); 
      this.InvokeEx(x => x.toolStripStatusLabel1.Text = x.toolStripProgressBar1.Value.ToString()); 
      this.InvokeEx(x => x.dataGridView1.Rows.Add(singleLine.Split(';'))); 
      this.InvokeEx(x => x.listBox1.Items.Add("Processed Line: " + singleLine)); 
     } 

На самом деле, я не привык писать классы, надеюсь, что эта первая настоящая попытка в порядке. Мне нужно больше комментариев, чтобы увидеть, есть ли лучший способ сделать это.

КСТАТИ FileHelpers только для .NET 1.1 и 2.0, есть поддержка не .NET 4.5, какая Питти за отличную один ..

Смежные вопросы