【问题标题】:Sort on list of objects that contains dictionary对包含字典的对象列表进行排序
【发布时间】:2015-08-24 23:55:42
【问题描述】:

这是我的对象:

public class A
{
public string Name { get; set; }    
public Dictionary<int, List<int>> Years { get; set; }
}

字典包含年份列表和月份列表。我希望先按年然后按月对 A 列表 进行排序。

每个 A 上的字典样本:

{2015,new List(){3,4,5,6}}
{2016,new List(){2,8,9,10}}

如果我有多年,那么它可以排序如下: 2015 然后 2015, 2016 然后 2016

我未能实现 IComparable 或使用任何现有的扩展方法,如 OrderBy 或 Sort。谢谢!

【问题讨论】:

  • 你将如何对A1: ( {10, {0}}, {12, {0}} ), A2: ( {11, {0}}, {13, {0}} ) 进行排序? A1 是否应该先行,因为它的最低年份在 A2 最低年份之前?还是您将每个 A 拆分成一个大 A,例如 {10,..}, {11,..}, {12,..}, {13,..}
  • 是的,首先是 A1,然后是 A2。没有拆分,因为它会复制对象 A。谢谢!!

标签: c# linq sorting dictionary


【解决方案1】:

我将 IComparable 添加到您的 A 类(当然您可以提取并作为委托传递......)

fiddlerlink

注意: 为简单起见,我假设列表已排序。否则在您的场景中的适当位置添加您的排序:)

基本上返回第一个不等于年或月的比较。 您可以通过 MyListOfAs.Sort() 调用它;

public class A:IComparable<A>
{
    public string Name { get; set; }
    public Dictionary<int, List<int>> Years { get; set; }

    private int complists(List<int> a, List<int> b)
    {
        var iret = (from i in Enumerable.Range(0, Math.Min(a.Count, b.Count))
                     where a[i].CompareTo(b[i]) != 0
                     select a[i] > b[i] ? 1 : -1).FirstOrDefault();

        return iret;
    }
    public int CompareTo(A other)
    {
        var mykeys = this.Years.Keys.ToList();
        var otherkeys = other.Years.Keys.ToList();

        var iret = (from i in Enumerable.Range(0, Math.Min(mykeys.Count, otherkeys.Count))
                     let yearDiff = mykeys[i].CompareTo(otherkeys[i])
                     let monthDiff = complists(this.Years[mykeys[0]], other.Years[otherkeys[0]])
                     where yearDiff != 0 || monthDiff != 0
                     select yearDiff != 0 ? yearDiff : monthDiff).FirstOrDefault();

        return iret != 0 ? iret : mykeys.Count > otherkeys.Count ? 1 : mykeys.Count < otherkeys.Count ? -1 : 0;
    }    }

【讨论】:

  • 谢谢!检查dotnetfiddle.net/w7Sywg 知道为什么“a14”没有排在首位吗?它只有 2015 年。
  • 在复古规范中我认为我错了(我更新了上面的解决方案)我将 a 中的 x 和 b 中的 y 更改为序数比较,然后添加了我没有的列表计数不考虑第一次:/我希望这至少能让你走上正确的(有用的)轨道:)
  • 谢谢。它仍然无法正常工作。我在 2015 年又添加了一个对象。请检查小提琴。
  • 你指的是哪个小提琴链接?这个首先显示 a14 dotnetfiddle.net/VCtz7s
  • 那么 a19 有 6,8,11,2 比其他有 6,7,8,9,10,11 的更大,因为(第二个元素更大)8>7 a14 仍然你的第一个原因它等于那些具有相同 2015 年值但只有一年的人
【解决方案2】:

我认为应该这样做:listOfA.OrderBy(a =&gt; a.Years.Min(y =&gt; y.Key + y.Value.Min() / 13d))

例如,如果字典中最小的年份和月份是 2000 年 1 月,则其值为 2000 + 1/13 = 2000.0769

那么剩下的就是从每个字典中选择最小值,然后按那个值排序。

注意 13 的值也可以是 20,如果您出于某种原因想要更好的数字,但 12/x 的最大部分必须小于 1 才能适当地给予年份更多的重要性,所以x必须大于12。这假设月份的范围是1到12(含)。


示例 I/O:

var listOfA = new List<A>
              {
                  new A
                  {
                      Name = "a1",
                      Years = new Dictionary<int, List<int>>
                              {
                                  {2015, new List<int> {3, 4, 5, 6}},
                                  {2016, new List<int> {2, 8, 9, 10}}
                              }
                  },
                  new A
                  {
                      Name = "a2",
                      Years = new Dictionary<int, List<int>>
                              {
                                  {2013, new List<int> {3, 4, 5, 6}},
                                  {2014, new List<int> {2, 8, 9, 10}}
                              }
                  },
                  new A
                  {
                      Name = "a3",
                      Years = new Dictionary<int, List<int>>
                              {
                                  {2015, new List<int> {3, 4, 5, 6}},
                                  {2014, new List<int> {2, 8, 9, 10}}
                              }
                  },
                  new A
                  {
                      Name = "a4",
                      Years = new Dictionary<int, List<int>>
                              {
                                  {2014, new List<int> {1, 4, 5, 6}},
                                  {2017, new List<int> {2, 8, 9, 10}}
                              }
                  }
              };

// listOfA is now {a1, a2, a3, a4}
listOfA = listOfA.OrderBy(a => a.Years.Min(y => y.Key + y.Value.Min() / 13d)).ToList();
// listOfA is now {a2, a4, a3, a1}

【讨论】:

  • 谢谢Yorye!它不适合我。你可以添加两个只有 2015 和 2016 的对象吗?它在 2015 年失败了。
  • 分享您的版本和预期顺序的粘贴箱。
  • @YoryeNathan - 不要使用 pastebin - 请改用 dotnetfiddle.net。您实际上可以在那里运行代码。
  • @ManishJain 我不是说要分享你的问题版本。我的意思是分享我的代码失败的示例。 (更不用说,你刚刚从 cechode 的回答中创建了一个提琴手的副本,这几乎不是我要求的)
  • 糟糕。我修改了原始代码。但是,数据仍然有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-31
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-15
相关资源
最近更新 更多