排序List时修剪

时间:2014-11-13 10:01:04

标签: c# list sorting datagridview trim

我正在读取分号分隔文件中的行,我在这里找到了如何对List进行排序:

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中使用trim,因为如果我不这样做,我将无法正确排序..

无论如何,当我需要将列表复制到另一个列表或将它们写入DataGridView时,我必须再次使用trim:

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

我不想在填充DataGridView时修剪字段,我只想在排序时修剪所有字段,这可能吗?

2 个答案:

答案 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%确定它有效,没有测试它,但你可以看到概念是什么。)

恕我直言,如果你将你的行首先转换为更有意义的对象,你会更好,例如使用FileHelpers。对“拆分字符串的第四部分”进行排序基本上没有意义,是恕我直言的错误代码,因为它要求你弄清楚输入文件的格式;将一行转换为具有意义的对象(例如,第一部分是ID,第三部分是名称等),允许您编写更有意义的代码。

BTW Microsoft doesn't like Hungarian notation WRT to C#:sList和sSortedList等开头的“s”。另外,我建议不要在it isn't one时命名为“sortedList”。

答案 1 :(得分: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));
        }
实际上,我不习惯写课,希望这第一次真正的尝试是可以的。我需要更多评论,看看是否有更好的方法。

BTW,FileHelpers仅适用于.NET 1.1和2.0,没有.NET 4.5支持,这对于这个优秀的人来说真是太可怜了。