获取数字范围内的重复

时间:2018-01-02 20:07:13

标签: vb.net linq filtering

我有一个DataTable,它包含大约2500行数据,如下所示:

+------------+---------+---------+---------+---------+
|    Date    | Number1 | Number2 | Number3 | Number4 |
+------------+---------+---------+---------+---------+
| 12/30/2017 |    1    |    11   |   19    |    72   |
| 12/29/2017 |    4    |    7    |   21    |    48   |
|    etc.    |   etc.  |   etc.  |   etc.  |   etc.  |
+------------+---------+---------+---------+---------+

我想要做的是获取不止一次出现的数字范围。有几点需要注意,最小数字是1,最大数字是100,数字是根据其范围递增排序的,这意味着像我的样本数据的第1行一样,它是1,11, 19 ,72和row2它是4,7, 21 ,48。

我确信通过For / Next循环简单地执行多次传递可能很简单,但我真的想通过LINQ查询甚至通过DataTable.Select方法更简洁一些

为了澄清,我使用的是Visual Basic .NET,数据来自CSV文件。虽然如果你提供一个C#例子,我可以很容易地翻译它。

3 个答案:

答案 0 :(得分:0)

这是使用Tuple类的固定数字长度的示例。     https://dotnetfiddle.net/mfgpZO

Dim numbers as Integer = 3
        Dim dt as new Data.DataTable
        dt.Columns.Add("Date", GetType(DateTime))
        For i as Integer = 1 to numbers
        dt.Columns.Add("Number" & i, GetType(integer))
        Next

    dt.rows.Add(new Object(){"12/29/2016", "1", "2", "3"})
    dt.rows.Add(new Object(){"12/30/2016", "4", "2", "3"})
    dt.rows.Add(new Object(){"12/31/2016", "1", "2", "3"})

    Dim d as new System.Collections.Generic.Dictionary(Of Tuple(Of Integer, Integer, Integer), String)
    For Each row as Data.DataRow in dt.Rows


    Dim t as new Tuple(Of Integer, Integer, Integer)(row("Number1"), row("Number2"), row("Number3"))

If d.ContainsKey(t) Then
        Console.WriteLine("Duplicate Set Of Numbers " & d(t) & " " & row("Date").ToString())
    Else
        d.Add(t, row("Date").ToString())
        Console.WriteLine("Not a Duplicate")
    End If



    Next

答案 1 :(得分:0)

这是C#代码。

LINQ的美丽之处在于,一旦有了解决方案,就可以应用AsParallel()并以并行方式运行解决方案。

<强> 1。将每一行映射为整数。

遵循标识符功能。

int identifier(DataRow dr)
{
    return row.Field<int>(0) + 
           row.Field<int>(1) * 100 +
           row.Field<int>(2) * 10000 +
           row.Field<int>(3) * 1000000;
} 

<强> 2。然后按标识符对行进行分组,并对具有多个条目的过滤器组进行分组。

这将提供所有重复的事件。

dt.Select(row => new { Row = row, id = identifier(row)})
  .GroupBy(r => r.id)
  .Where(g => g.Count() > 1)
  .Select(g => g.First());

答案 2 :(得分:0)

这是Linq-esque“Duplicated”功能的一个例子。这是一个私有实现,进行错误处理的公共扩展方法留给读者练习。该函数旨在推迟执行,行进足够远,以便在每次迭代时找到下一个副本。

Private Iterator Function Duplicates(Of TSource)(ByVal source as IEnumerable(Of TSource), ByVal comparer As IEqualityComparer(Of TSource)) As IEnumerable(Of TSource)

    Dim seenElements As New HashSet(Of TSource)(comparer)
    Dim returnedElements As New HashSet(Of TSource)(comparer)

    For Each item In source
        'If adding to the set of seen elements fails, then this element is a duplicate.
        'Then, if adding to the set of returned elements succeeds, this element has not been returned before.
        If Not seenElements.Add(item) AndAlso returnedElements.Add(item) Then Yield item
    Next
End Function