在另一个模型列表内的模型列表中求和和分组

时间:2018-12-07 19:25:46

标签: c# list linq

这是我的第一个问题,如果出现问题,请抱歉。

我正在使用具有以下型号的应用程序:

public class OrderDetails {
 int DetailID {get; set;}
 List<Taxes> taxes {get; set;}
}

public class Taxes {
 int TaxID {get; set;}
 decimal TaxValue {get; set;}
}

因此在代码中,我有一个List<OrderDetails>,其中有很多物品,而这些物品具有不同的税金,但大多数物品具有相同的税金。 我需要创建一个List<Taxes>常规,在其中我将拥有List<OrderDetails>中的所有税款和它们的值的总和,我认为这是使用总和的一个组,但我不知道如何应用该组在列表内的列表中。

您能知道这是否可行,或者是否存在其他方式吗?

非常感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

您的标准尚不明确,因此,这里有一些我认为是您想要的解决方案。

使用SelectMany展平嵌套序列,然后按TaxId分组,然后使用Select进行变换:

var result = orderDetailses.SelectMany(x => x.taxes)
            .GroupBy(x => x.TaxID)
            .Select(x => new Taxes
            {
                TaxID = x.Key,
                TaxValue = x.Sum(e => e.TaxValue)                    
            }).ToList();

或者您正在寻找:

var result = orderDetailses.SelectMany(o => o.taxes.Select(t => (TaxId: t.TaxID, orderDetailses: o)))
                .GroupBy(i => i.TaxId)
                .Select(e => new Taxes
                {
                    TaxID = e.Key,
                    TaxValue = e.SelectMany(x => x.orderDetailses.taxes)
                        .Sum(a => a.TaxValue)
                }).ToList();

答案 1 :(得分:0)

您写道:

  

物品有不同的税款,但大多数物品有相同的税款

您要做的最重要的事情是定义两个税款何时相等。当它们具有相等的TaxIdTaxValue时是它,还是当它们具有相同的TaxValue时是它,还是应该是相同的对象。因此,这五种税收中的哪一种相等:

Taxes a = new Taxes {Taxid = 1, TaxValue = 3};
Taxes b = new Taxes {Taxid = 1, TaxValue = 4};
Taxes c = new Taxes {Taxid = 2, TaxValue = 4};
Taxes d = new Taxes {Taxid = 2, TaxValue = 4};
Taxes e = d;

如果答案是:它取决于:有时仅d == e(相同的对象),有时b == c == d == e(等于TaxValue),那么您应该提供一个相等比较器:实现IEqualityComparer<Taxes>

通常答案不是那么困难,我想您要说的是,如果两个Taxes具有相同的TaxValue,则它们是相等的

所以您的要求如下:

  • 输入:一系列OrderDetails。每个OrderDetail都有一个DetailId和一系列零个或多个Taxs。每个税收都有一个TaxId和一个TaxValue。
  • 如果两个Tax具有相同的TaxValue,则视为相等。
  • 请求的输出:来自每个OrderDetail的DetailId及其所有唯一税的序列。

要选择输入项的属性,请使用Enumerable.Select要仅保留序列的唯一输出值,请使用Enumerable.Distinct

var result = myOrderDetails               // take my sequence of OrderDetails
    .Select(orderDetail => new            // from every orderDetail in this sequence make one new object
    {                                     // with the following properties
         DetailId = orderDetail.DetailId,

         TaxValues = orderDetail.Taxes    // from all Taxes of this orderDetail,
            .Select(tax => tax.TaxValue)  // select only the TaxValues
            .Distinct(),                  // and remove duplicates

         // or if two taxValues are equal if they are the same object:
         Taxes = orderDatail.Taxes          // from all Taxes of this orderDetail
             .Distinct()                    // remove duplicates
             .Select(tax => tax.TaxValue),  // and keep only the TaxValue (optional)
    });

如果关于税收平等的想法不是那么简单,例如,将平等定义为:

  

如果两个税收具有相等的TaxId和相等的TaxValue,则它们是相等的

在这种情况下,您必须编写一个相等比较器。它们不是很困难,但是您应该记住一些事情:

  • 如何处理Null值?如果两者都为空,则它们相等吗?
  • 请记住,TaxValue的派生类通常不等于TaxValue本身

考虑阅读Define Value Equality for a Type

class TaxesEqualityComparer : EqualityComparer<TaxValue>
{

    public static readonly IEqualityComparer<TaxValue> ValueComparer
           = new TaxesEqualityComparer()

    public override bool Equals(TaxValue x, TaxValue y)
    {
        // the following lines are almost always the same:
        if (x == null) return y == null;               // true if both null
        if (y != null) return false;                   // because x not null and y is null
        if (Object.ReferenceEquals(x, y) return true;  // optimalization: same object
                                                       // no need to check the properties
         if (x.GetType() != y.GetType()) return false; // not same type

         // here start the differences of default Taxes comparison
         // when would you say that two Taxes are equal?
         return x.TaxId == y.TaxId
             && x.TaxValue == y.TaxValue;
    };

    public override int GetHashCode(x)
    {
        ...
    }
}

GetHashCode是诸如Dictionary,Sets之类的类和诸如Distinct()之类的函数所使用的一种优化,用于快速查找不平等。没有定义此功能的“最佳”方法。 Stack overflow: Best algorithm for GetHashCode可能会对您有所帮助。

一旦定义了类,就可以在Distinct中使用相等比较器:

// use default equality (= equal if same object)
...
.Distinct(TaxesEqualityComparer.Default)

// use your own definition of Taxes equality:
...
.Distinct(TaxesEqualityComparer.ValueComparer)