棘手的LINQ查询:返回包含最大长度子字符串的子字符串的字符串

时间:2016-03-27 18:05:04

标签: vb.net linq

我有2个数据表,每个数据表有300,000行(从带有OLEDB的2个excel工作表导入的数据表)。

第一个数据表是'dtTosearch',第二个数据表是'sourceDt'。

这是2个表的示例:

datatables example

我需要为'untagged'列(sourceDt)中的每一行找到与'token'列(dtTosearch)中每一行的匹配项。匹配条件是:

  1. 'site'value ='site'value
  2. 'cat'value ='category'value
  3. 未标记的值必须包含标记值
  4. 如果上述所有条件都存在超过一个匹配,则查询必须恢复具有最大长度的令牌匹配。 (这是我没有弄清楚如何执行的棘手部分 LINQ)
  5. 这个任务必须在最短的处理时间内运行 - 因为它的要求,因为它更专业,因为我与朋友 - 同事-JAVA热心的开发人员打赌,.NET将运行得更快(简单的白天( - :)< / LI>

    我添加了代码的相关部分,它工作正常,但不是我想要的方式,我想改善处理时间,看看linqQuery()函数中的foreach循环 - 如果你帮助我,我将感激不尽通过将我的查询扩展到条件数4来替换该循环,循环操作条件4,因为按“令牌”长度排序的linq查询的结果以降序排列,因此它将退出并返回具有最大行长度的结果

    Private Sub startScanning()
        Dim siteNum As Double
        Dim categoryNum As Double
        Dim stringToSearchin As String
    
        For i = 0 To sourceDt.Rows.Count - 1
            siteNum = sourceDt.Rows(i).Item(0)
            categoryNum = sourceDt.Rows(i).Item(1)
            stringToSearchin = sourceDt.Rows(i).Item(3)
           Debug.WriteLine( linqQuery(siteNum, categoryNum, stringToSearchin) & " " &
               stringToSearchin)
        Next
    End Sub
    
    Private Function linqQuery(ByVal sitenum As Double, ByVal cat As Double,
                               ByVal stringToSearchIn As String) As String
    
        Dim query = From row In dtTosearch
                    Where (row.Field(Of Double?)("site") = sitenum And
                    row.Field(Of Double?)("category") = cat)
                    Order By row.Field(Of String)("token").Length Descending
                    Select New With {
                        .token = row.Field(Of String)("token")
             }
    
    
        For Each x In query
            If stringToSearchIn.Contains(x.token) Then
                Return x.token
                Exit Function
            End If
        Next
    
        Return ""
    End Function
    

    非常感谢你的时间和考虑!

1 个答案:

答案 0 :(得分:5)

在C#代码中,您可以找到所需的记录

from r1 in sourceDt.AsEnumerable()
join r2 in dtToSearch.AsEnumerable() 
    on new { p1 = r1.Field<int>("cat"), p2 = r1.Field<int>("Site") }
    equals new { p1 = r2.Field<int>("category"), p2 = r2.Field<int>("site") }
    into r2g
select new
{
    r1,
    p2 = (from r2 in r2g
          let token = r2.Field<string>("token")
          where token.Contains(r1.Field<string>("untagged"))
          orderby token.Length descending, token
          select r2).FirstOrDefault()
}

也就是说,首先组加入他们必须共有的字段上的数据表。 join - into语法使这成为一组加入,如here所述。

然后,在一组匹配的行中,过滤了untagged中包含token值的行,并返回具有最长令牌的行(也按字母顺序返回第一个,如果长度有关系)。