【问题标题】:How to multiply a column under a certain condition by using linq?如何使用linq在特定条件下乘以一列?
【发布时间】:2013-07-12 08:20:05
【问题描述】:

假设我有一个像这样的数据表:

Date       |  Qty | Price
20/10/2013 |  3   |  1.25
21/10/2013 |  5   |  1 
22/10/2013 |  2   |  0.75
24/10/2013 |  1   |  0.90

如果日期在 2013 年 10 月 22 日之后,我想将列价格乘以 0.98。

我已经为此编写了一些代码,但我想用 linq 来做,你知道我该怎么做吗?

谢谢

【问题讨论】:

  • 处理后的预期输出是什么?数据表、列表?
  • 需要一个数据表

标签: c# linq datatable


【解决方案1】:

LINQ 是关于查询,而不是更新。您可以使用它来查询应该更新的行,但仍然必须自己进行更新,例如使用foreach循环:

foreach(var row in dt.AsEnumerable().Where(x => x.Field<DateTime>("Date") >= myDateTime))
    row.SetField<double>("Price", row.Field<double>("Price") * 0.98);

【讨论】:

  • SetField 不会修改原来的行吗?
【解决方案2】:

因为您想更新DataTable,所以我认为没有理由在这里使用 LINQ。相反,我只使用DataTable.Select Method:

var d = new DataTable();
d.Columns.Add("Date", typeof(DateTime));
d.Columns.Add("Qty", typeof(int));
d.Columns.Add("Price", typeof(double));
d.Rows.Add(DateTime.ParseExact("20/10/2013", "dd/MM/yyyy",
    CultureInfo.InvariantCulture), 3, 1.25);
d.Rows.Add(DateTime.ParseExact("21/10/2013", "dd/MM/yyyy",
    CultureInfo.InvariantCulture), 5, 1.0);
d.Rows.Add(DateTime.ParseExact("22/10/2013", "dd/MM/yyyy",
    CultureInfo.InvariantCulture), 2, 0.75);
d.Rows.Add(DateTime.ParseExact("24/10/2013", "dd/MM/yyyy",
    CultureInfo.InvariantCulture), 1, 0.90);

foreach (var item in d.Select("Date >= #10/22/2013#"))
{
    item.SetField("Price", item.Field<double>("Price") * 0.98);
}

【讨论】:

  • 只需将 item[] 更改为 item.SetField, item.Field 即可:P
【解决方案3】:

首先您需要添加System.Data.DataSetExtensions。然后您可以使用 Where() 例如选择相关行。

var rows=from row in myTable.AsEnumerable()
         where row.Field<DateTime>("Date")>=new DateTime(2013,10,22(
         select rows;

然后可以循环修改行值:

foreach(var row in rows)
{
    row["Price"]=0.98m*(decimal)row["Price"];
}

或者,为了避免装箱和拆箱操作,您可以使用 DataSetExtensions 中的SetField

foreach(var row in rows)
{
    row.SetField<decimal>("Price",row.Field<decimal>("Price")*0.98m);
}

如果您不想更新原始行但又想获得一个修改了匹配行的新表,那么事情会变得有点棘手。如果日期条件匹配,您必须克隆 Select 中的每个 DataRow 并设置适当的字段。

一个更简单的解决方案是简单地使用DataTable.Clone 克隆原始表并将更改应用于克隆。这不会影响性能,因为无论如何您都会复制原始数据。

你可以这样做:

var myCopy=myTable.Clone();
var rows=from row in myClone.AsEnumerable()
         where row.Field<DateTime>("Date")>=new DateTime(2013,10,22(
         select rows;
foreach(var row in rows)
{
    row.SetField<decimal>("Price",row.Field<decimal>("Price")*0.98m);
}

【讨论】:

  • @MarcinJuraszek Nitpicking:P
猜你喜欢
  • 2013-07-12
  • 2020-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-19
  • 1970-01-01
  • 2022-08-04
  • 1970-01-01
相关资源
最近更新 更多