【问题标题】:Find longest string in Datatable column在数据表列中查找最长的字符串
【发布时间】:2019-04-15 22:48:27
【问题描述】:

我想知道是否可以创建一个“单行”Linq 来检索特定 Datatable 列的最长字符串值,这意味着所有列数据(数字、日期、字符串...)都应转换为字符串然后返回最长的字符串。

我发现的只是如何从列表中获取最长的字符串,或最大长度值。

这是我迄今为止尝试过的(长度错误):

string maxString = dt
  .AsEnumerable()
  .Select(row => row[mycolumn].ToString())
  .Where(s => s.OrderByDescending(st => st.Length).First());

【问题讨论】:

  • "这是我目前尝试过的(显然不行)" > 不是很明显,请解释一下。
  • @PatrickHofman,抱歉,此代码返回“char 不包含长度定义”
  • 无需使用Where()。这应该可以解决问题:.Select(row => row[mycolumn].ToString()).OrderByDescending(st => st.Length).First();
  • @StephanBauer,这很快。谢谢,我知道它必须是那么简单:)
  • 如果您从数据库中加载该数据表,您可能应该考虑编写 SQL 来代替。将整个表加载到内存中并使用 Linq 进行处理可能会慢很多。

标签: c# linq


【解决方案1】:

您正在寻找ArgMax - 一个,它具有某种属性的最大值。标准 Linq 不提供 ArgMax 但您可以通过 Aggregate 实现它(即从序列中获取单个值):

 string maxString = dt
   .AsEnumerable()
   .Select(row => row[mycolumn].ToString())
   .Aggregate((s, a) => a.Length > s.Length ? a : s);

【讨论】:

  • 此解决方案可能比接受的答案快得多,因为它不必实际对列表进行排序,只需迭代一次。
  • @Marie 是的,我测试过,这是最快的。尽管在我使用 OpenXML 将 320k+ 行和 7 列的数据导出到 Excel 的测试中,它与 Gilad Green 的答案相比相差 1 秒。
【解决方案2】:

你快到了:

string maxString = dt.AsEnumerable()
                     .Select(row => row[mycolumn].ToString())
                     .OrderByDescending(st => st.Length).FirstOrDefault();

Where 需要一个谓词(返回真或假的函数)。相反,只需像您一样订购投影(.Select)并检索第一项。


注意这是一个O(nlogn) 解决方案,可以通过不排序但通过查找具有最大长度的项目来改进为O(n) 解决方案。一种可能的方法是在 Dimitry 的回答中。对于数量不多的藏品,我不确定人们是否真的能感受到差异,但确实值得注意这一点。


请注意,您还可以使用可以通过 Nuget 添加的 MoreLinq's .MaxBy(对于 GitHub repo),这将为您提供 O(n) 性能和所需的“单线”:

var row = dt.AsEnumerable().MaxBy(r => r[mycolumn].ToString().Length);

【讨论】:

  • 排序以获得最大值不是效率低下吗?还是 LINQ 对此进行了优化?
  • @RoadRunner - 你说得对,排序效率会降低。这是一个 O(nlogn) 解决方案,而可以按照下面的答案执行 O(n)。我试图尽可能接近原作
  • IMO 你不应该推荐 FirstOrDefault,你应该首先推荐一个健全性检查。那你就不用担心会弹出null了。
【解决方案3】:

首先不要在dt.之后使用AsEnumerable。 以某种方式这样写:

dt.OrderByDescending(row => row[mycolumn].Length).First();

【讨论】:

  • AsEnumerable 不应使用,因为它将计算传输到应用程序内存,当我的示例强制它在 sql server 执行计算时。当所有计算完成后 First() 将结果传输到应用程序内存。试试我的例子,告诉我它是否有效,好吗?
  • @Lucy82,好吧,我检查了我的示例,它运行良好:)。但是正如上面的人所注意到的,通过聚合函数找到最大值会好得多。 OrderBy 排序只需要 1 个周期。
  • @Lucy82 接受的答案和 Dmitry 的答案都不适用于持久保存在数据库中的大型数据集。 IE。如果 dt 是数据库中的表并且包含数千行,则其他答案将首先获取所有这些行,然后进行排序以获得最大值。
  • @NoImagination 我可能错了,但问题没有标记实体或任何东西。只有当他们使用支持该功能的 ORM 时,“当我的示例强制它在 sql server 执行计算时”才正确?
  • @NoImagination 按道理,“dt”代表 DataTable(row[column] 部分对于 EF 查询也毫无意义),这意味着关闭 AsEnumerable 根本行不通.这也意味着数据已经在内存中,所以那里真的没有丢失任何东西。
猜你喜欢
  • 2014-03-20
  • 1970-01-01
  • 2021-02-14
  • 1970-01-01
  • 2020-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-19
相关资源
最近更新 更多