字典排序

我正在使用这个var ordered = 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 dictionary = new Dictionary(); List lineList = new List(); 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++; } 

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

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

这不会修改您的密钥 – 它只会影响排序。

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

编辑:

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

 public class CustomComparer: IComparer { 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. } } 

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

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

哪里

 private class CodeComparer : IComparer { 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 (ie bigger) item come after the shorter return leftComponents.Length.CompareTo(rightComponents.Length); } }