使用c#

时间:2018-03-09 10:22:35

标签: c# csv

我必须在csv文件中对多个列进行排序。 我文件的一部分是这样的:

Number | Section | Color | Length | Panel1 | Panel2 | Description
1          1.5      BK      200     PAN5A    PAN5B     ABC
2          0.75     BK      620     PAN3A    PAN3A     ACC
3          2        RD      150     PAN2A    PAN2A     AAA
4          1.5      BL      500     PAN2A    PAN2A     ABB
5          0.75     GY      250     PAN1A    PAN2A     AAA
6          5.25     GY      200     PAN3A    PAN3B     CCC
7          1.25     BU      150     PAN4A    PAN4A     DDD
8          0.75     BK      800     PAN4A    PAN4A     BBB

我必须按特定顺序订购第3列(颜色)。我必须遵循的顺序是以下(GY,BL,RD,其他颜色,BK),是颜色的首字母缩略词。 然后我必须按编号对第2列(部分)进行订购,第4列(长度)也按编号订购。

目标是拥有以下csv文件。

Number | Section | Color | Length | Panel1 | Panel2 | Description
5          0.75     GY      250     PAN1A    PAN2A     AAA
6          5.25     GY      200     PAN3A    PAN3B     CCC
4          1.5      BL      500     PAN2A    PAN2A     ABB
3          2        RD      150     PAN2A    PAN2A     AAA
7          1.25     BU      150     PAN4A    PAN4A     DDD`
2          0.75     BK      620     PAN3A    PAN3A     ACC
8          0.75     BK      800     PAN4A    PAN4A     BBB  
1          1.5      BK      200     PAN5A    PAN5B     ABC

下面我放了我的代码,但它有问题。由于第3列按字母顺序排序,因此第2列和第4列将数字视为字符串,因此不遵循正确的顺序。

var sorted = File.ReadLines(pathFile)
            .Select(line => new
            {
                SortKeyColor = line.Split(';')[2],
                SortKeySection = line.Split(';')[1],
                SortKeyLenght = line.Split(';')[3],
                Line = line
            })
            .OrderBy(x => x.SortKeyColor)
            .ThenBy(x => x.SortKeySection)
            .ThenBy(x => x.SortKeyLenght)
            .Select(x => x.Line);

            File.WriteAllLines(pathNewFile, sorted);

我也试过把Int32.Parse但我得到异常“输入字符串格式不正确。”

SortKeySection = Int32.Parse(line.Split(';')[1]),

3 个答案:

答案 0 :(得分:0)

您会收到格式异常,因为第1列(实际上是第二列)不是整数。这应该有效:

.ThenBy(x => double.Parse(x.SortKeySection))
.ThenBy(x => int.Parse(x.SortKeyLenght))

但调整SortKeySectionSortKeyLength的类型并分配正确的数据类型会更好(也更快):

SortKeySection = double.Parse(line.Split(';')[1]),
SortKeyLenght = int.Parse(line.Split(';')[3]),

根据您的语言环境,您可能希望添加特定的文化,例如:

double.Parse(line.Split(';')[1], CultureInfo.InvariantCulture)

如果您的本地数字格式具有不同的小数点分隔符,例如,;

对于颜色的正确顺序,您可能希望使用自定义IComparer<string>,以便更好地控制哪个元素应该先于另一个元素。例如,此实现首先对GYBLRD进行排序,然后按字母顺序对所有其他内容进行排序,然后对所有BK进行排序:

public class ColorNameComparer : IComparer<string>
{
    private readonly List<string> colorOrder = new List<string>{"GY", "BL", "RD"};
    public int Compare(string x, string y)
    {
        if (x == y) return 0;

        if (x == "BK") return 1;
        if (y == "BK") return -1;

        if (colorOrder.Contains(x) && colorOrder.Contains(y))
            return colorOrder.IndexOf(x) > colorOrder.IndexOf(y) ? 1 : -1;
        if (colorOrder.Contains(x))
            return -1;
        if (colorOrder.Contains(y))
            return 1;

        return String.Compare(x, y, StringComparison.Ordinal);
    }
}

可以像这样使用:

.OrderBy(x => x.SortKeyColor, new ColorNameComparer())
using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;

namespace ConsoleApp
{
    public class Program
    {
        public static void Main()
        {
            string file =
                "1;1.5;BK;200;PAN5A;PAN5B;ABC\r\n" +
                "2;0.75;BK;620;PAN3A;PAN3A;ACC\r\n" +
                "3;2;RD;150;PAN2A;PAN2A;AAA\r\n" +
                "4;1.5;BL;500;PAN2A;PAN2A;ABB\r\n" +
                "5;0.75;GY;250;PAN1A;PAN2A;AAA\r\n" +
                "6;5.25;GY;200;PAN3A;PAN3B;CCC\r\n" +
                "7;1.25;BU;150;PAN4A;PAN4A;DDD\r\n" +
                "8;0.75;BK;800;PAN4A;PAN4A;BBB";
            string[] lines = file.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            var sorted = lines.Select(line => new
                {
                    SortKeyColor = line.Split(';')[2],
                    SortKeySection = double.Parse(line.Split(';')[1], CultureInfo.InvariantCulture),
                    SortKeyLenght = int.Parse(line.Split(';')[3]),
                    Line = line
                }

            ).OrderBy(x => x.SortKeyColor, new ColorNameComparer()).ThenBy(x => x.SortKeySection).ThenBy(x => x.SortKeyLenght).Select(x => x.Line);
            foreach (var entry in sorted)
                Console.WriteLine(entry);
        }
    }

    public class ColorNameComparer : IComparer<string>
    {
        private readonly List<string> colorOrder = new List<string> {"GY", "BL", "RD"};

        public int Compare(string x, string y)
        {
            if (x == y)
                return 0;
            if (x == "BK")
                return 1;
            if (y == "BK")
                return -1;
            if (colorOrder.Contains(x) && colorOrder.Contains(y))
                return colorOrder.IndexOf(x) > colorOrder.IndexOf(y) ? 1 : -1;
            if (colorOrder.Contains(x))
                return -1;
            if (colorOrder.Contains(y))
                return 1;
            return String.Compare(x, y, StringComparison.Ordinal);
        }
    }
}

答案 1 :(得分:0)

您可以使用临时int值替换“SortKeyColor”的值进行排序:

         // Converting string to integers with the desired order
         Func<string, int> converter = (color) =>
         {
             switch (color)
             {
                 case "GY": return 0;
                 case "BL": return 1;
                 case "RD": return 2;
                 case "BK": return 4;
                 default: return 3;
             }
         };

        var sorted = File.ReadLines("")
        .Select(line => new
        {
            SortKeyColor = converter(line.Split(';')[2]),
            SortKeySection = double.Parse(line.Split(';')[1]),
            SortKeyLenght = int.Parse(line.Split(';')[3]),
            Line = line
        })
        .OrderBy(x => x.SortKeyColor)
        .ThenBy(x => x.SortKeySection)
        .ThenBy(x => x.SortKeyLenght)
        .Select(x => x.Line);

编辑:我添加了转换方法。

答案 2 :(得分:0)

尝试实现自定义比较器

    public class CustomComparer : IComparer<string>
    {
        Dictionary<string, int> colorPriorities;
        public CustomComparer()
        {
            colorPriorities = new Dictionary<string, int>();
            colorPriorities.Add("GY", 1);
            colorPriorities.Add("BL", 2);
            colorPriorities.Add("RD", 4);
            colorPriorities.Add("BK", 8);
        }
        public int GetPriority(string color)
        {
            if (!colorPriorities.ContainsKey(color))
            {
                return 5;
            }

            return colorPriorities[color];
        }
        public int Compare(string x, string y)
        {
            string xSortKeyColor = x.Split(';')[2];
            double xSortKeySection = Convert.ToDouble(x.Split(';')[1]);
            double xSortKeyLenght = Convert.ToDouble(x.Split(';')[3]);

            string ySortKeyColor = y.Split(';')[2];
            double ySortKeySection = Convert.ToDouble(y.Split(';')[1]);
            double ySortKeyLenght = Convert.ToDouble(y.Split(';')[3]);

            if (xSortKeyColor != ySortKeyColor)
                return GetPriority(xSortKeyColor).CompareTo(GetPriority(ySortKeyColor));

            if (xSortKeySection != ySortKeySection)
                return xSortKeySection.CompareTo(ySortKeySection);

            return xSortKeyLenght.CompareTo(ySortKeyLenght);
        }
    }