字典排序

发布于 2024-12-03 02:55:08 字数 2096 浏览 0 评论 0原文

我正在使用这个 varordered=dictionary.Keys.OrderBy(x => x); 来订购字典。

这对于按字母数字顺序对字典进行排序非常有效,我想保持这种方式并添加一些例外...

所以现在,有序字典的输出如下所示:

1: "0603C" "113456" 1
2: "0603C" "984132" 8
3: "0603R" "11115" 3
4: "0603R" "13554" 1
5: "1608C_1.0" "119764" 2
6: "1608C_1.0" "147429" 54
7: "1608R_1.0" "122951" 4
8: "1608R_1.0" "147446" 1
9: "1608R_1.0" "147448" 23
10: "3216" "110762" 2
11: "TANT23" "119764" 2
//more here...

..但我希望它看起来像这

1: "0603R" "11115" 3
2: "0603R" "13554" 1
3: "0603C" "113456" 1
4: "0603C" "984132" 8
5: "1608R_1.0" "122951" 4    //**NOTICE**: The "R" and "C" endings after 1608 and 0603
6: "1608R_1.0" "147446" 1    // were switched. I would like to switch all "C" and "R"
7: "1608R_1.0" "147448" 23   // endings if they are the same value before.
8: "1608C_1.0" "119764" 2
9: "1608C_1.0" "147429" 54
10: "3216" "110762" 2
11: "TANT23" "119764" 2
//more here...

是我的代码到目前为止的样子:

StreamWriter sw = new StreamWriter(saveFile.FileName);
Dictionary<string, int> dictionary = new Dictionary<string, int>();
List<string> lineList = new List<string>();
int j = 1;
lineList = theFuji1List.Select(line =>
{
    int nameLength = line.Name.Length;

    if (line.PartDescription != "")
        return line.PartDescription + " " line.PartNumber + " " + line.TWidth + " " + line.Name.Remove(1, nameLength - 1) + "\n";

    else
        return "N/A " + line.PartNumber + " " + line.TWidth + " " + line.Name.Remove(1, nameLength - 1) + "\n";
})
    .Where(x => !(x.Contains("FID") || x.Contains("EXCLUDE")))
    .ToLisT();

foreach (string word in lineList)
{
    if (dictionary.ContainsKey(word))
        dictionary[word]++;
    else
        dictionary[word] = 1;
}

var ordered = dictionary.Keys.Orderby(x => x);   //This is what I think I need to change?

foreach (string key in ordered)
{
    string[] splitKey = key.Split(' ');

    sw.WriteLine(string.Format("{0}: \"{1}\" \"{2}\" {3}", j, splitKey[0], splitKey[1], dictionary[key]));
    j++;
}

I am using this var ordered = dictionary.Keys.OrderBy(x => x); to order a dictionary.

This works great ordering the dictionary alpha-numerically and I would like to keep it this way and add a few exceptions...

So right now, the ordered dictionary looks like this for the output:

1: "0603C" "113456" 1
2: "0603C" "984132" 8
3: "0603R" "11115" 3
4: "0603R" "13554" 1
5: "1608C_1.0" "119764" 2
6: "1608C_1.0" "147429" 54
7: "1608R_1.0" "122951" 4
8: "1608R_1.0" "147446" 1
9: "1608R_1.0" "147448" 23
10: "3216" "110762" 2
11: "TANT23" "119764" 2
//more here...

..but I would like it to look like this:

1: "0603R" "11115" 3
2: "0603R" "13554" 1
3: "0603C" "113456" 1
4: "0603C" "984132" 8
5: "1608R_1.0" "122951" 4    //**NOTICE**: The "R" and "C" endings after 1608 and 0603
6: "1608R_1.0" "147446" 1    // were switched. I would like to switch all "C" and "R"
7: "1608R_1.0" "147448" 23   // endings if they are the same value before.
8: "1608C_1.0" "119764" 2
9: "1608C_1.0" "147429" 54
10: "3216" "110762" 2
11: "TANT23" "119764" 2
//more here...

This is what my code looks like so far:

StreamWriter sw = new StreamWriter(saveFile.FileName);
Dictionary<string, int> dictionary = new Dictionary<string, int>();
List<string> lineList = new List<string>();
int j = 1;
lineList = theFuji1List.Select(line =>
{
    int nameLength = line.Name.Length;

    if (line.PartDescription != "")
        return line.PartDescription + " " line.PartNumber + " " + line.TWidth + " " + line.Name.Remove(1, nameLength - 1) + "\n";

    else
        return "N/A " + line.PartNumber + " " + line.TWidth + " " + line.Name.Remove(1, nameLength - 1) + "\n";
})
    .Where(x => !(x.Contains("FID") || x.Contains("EXCLUDE")))
    .ToLisT();

foreach (string word in lineList)
{
    if (dictionary.ContainsKey(word))
        dictionary[word]++;
    else
        dictionary[word] = 1;
}

var ordered = dictionary.Keys.Orderby(x => x);   //This is what I think I need to change?

foreach (string key in ordered)
{
    string[] splitKey = key.Split(' ');

    sw.WriteLine(string.Format("{0}: \"{1}\" \"{2}\" {3}", j, splitKey[0], splitKey[1], dictionary[key]));
    j++;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

無處可尋 2024-12-10 02:55:08

只需将排序表达式的“R”修改为“B”,使其位于“C”之前:

var ordered = dictionary.Keys.Orderby(x => Regex.Replace(x, @"^(\d+)R", "$1B"));

这不会修改您的键 - 它只会影响排序。

Just modify the "R" to be a "B" for the sort expression, so that it falls before "C":

var ordered = dictionary.Keys.Orderby(x => Regex.Replace(x, @"^(\d+)R", "$1B"));

This won't modify your keys - it will only affect the sort.

じее 2024-12-10 02:55:08

OrderBy() 有一个重载 OrderBy(Func<>, IComparer<>),您可以将自己的比较器传递给它。

编辑:

您可以像这样实现自定义比较器类:

public class CustomComparer: IComparer<String>
{
    public int Compare(object x, object y)
    {
         // perform comparison
         // return 0 if two items are equal, less than zero if x is less than y, and greater than zero if x is greater than y.
    }
}

OrderBy() has an overload OrderBy(Func<>, IComparer<>) that you can pass your own comparer to.

EDIT:

You can implement your custom comparer class like this:

public class CustomComparer: IComparer<String>
{
    public int Compare(object x, object y)
    {
         // perform comparison
         // return 0 if two items are equal, less than zero if x is less than y, and greater than zero if x is greater than y.
    }
}
余罪 2024-12-10 02:55:08

我将在 IComparer 实现中使用正则表达式,并将其传递到 OrderBy 语句中

var ordered = dictionary.Keys.OrderBy(x => x, new CodeComparer());

private class CodeComparer : IComparer<string>
{
    public int Compare(string left, string right)
    {
        // TODO: Use a regex or other method to split into components
        string[] leftComponents, rightComponents;

        for (int i = 0; i < Math.Min(leftComponents.Length, rightComponents.Length; i++)
        {
            var componentComparison = StringComparer.InvariantCultureIgnoreCase.CompareTo(leftComponents[i], rightComponents[i]);
            if (componentComparison != 0)
            {
                if (i == 1) // Special case to flip the "R" and "C"
                {
                    return componentComparison * -1;
                }
                // TODO: Add any other special cases
                return componentComparison;
            }
        }

        // They are equal up to this point, therefore let the more detailed (i.e. bigger) item come after the shorter
        return leftComponents.Length.CompareTo(rightComponents.Length);
    }
}

I would use a regex within an IComparer implementation and pass this into the OrderBy statement:

var ordered = dictionary.Keys.OrderBy(x => x, new CodeComparer());

Where

private class CodeComparer : IComparer<string>
{
    public int Compare(string left, string right)
    {
        // TODO: Use a regex or other method to split into components
        string[] leftComponents, rightComponents;

        for (int i = 0; i < Math.Min(leftComponents.Length, rightComponents.Length; i++)
        {
            var componentComparison = StringComparer.InvariantCultureIgnoreCase.CompareTo(leftComponents[i], rightComponents[i]);
            if (componentComparison != 0)
            {
                if (i == 1) // Special case to flip the "R" and "C"
                {
                    return componentComparison * -1;
                }
                // TODO: Add any other special cases
                return componentComparison;
            }
        }

        // They are equal up to this point, therefore let the more detailed (i.e. bigger) item come after the shorter
        return leftComponents.Length.CompareTo(rightComponents.Length);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文