确定列表的什么值首先出现在字符串中的最快方法
Fastest way to determine what value of a list appears first in a string
我在 sheet 的列中有一个字符串列表(假设是 "A"),如下所示:
A
BJS-LAX-GRU
CAN-ORD-MIA-BOG
NRT-LAX-JFK-LIM
然后我在另一个 sheet 上有一个不同的列表(比如说 "B"),像这样:
A
LAX
MEX
MIA
JFK
所以我想知道第二个列表的哪个值首先出现在第一个列表的每个字符串中,然后我需要将该值写在字符串旁边。在这个例子中,我会得到:
A B
BJS-LAX-GRU LAX
CAN-ORD-MIA-BOG MIA
NRT-LAX-JFK-LIM LAX
我写了下面的代码,效果很好:
Dim aux As Integer
Dim cur As String
For j = 1 To Sheets("A").Cells(Rows.Count, "A").End(xlUp).Row
aux = 100
cur = ""
For k = 1 To Sheets("B").Cells(Rows.Count, "A").End(xlUp).Row
If InStr(Sheets("A").Cells(j, 1).Value, Sheets("B").Cells(k, 1).Value) < aux And InStr(Sheets("A").Cells(j, 1).Value, Sheets("B").Cells(k, 1).Value) <> 0 Then
cur = Sheets("B").Cells(k, 1).Value
aux = InStr(Sheets("A").Cells(j, 1).Value, cur)
End If
Next k
Sheets("A").Cells(j, 2) = cur
Next j
问题是我知道这段代码效率极低,因为这些列表有 20 万多行。有没有更有效的方法来做到这一点?
通过将值放入数组并使用 Application.Match 查找匹配项,这应该非常快:
Sub findmatch()
Dim inarr() As Variant
Dim oarr() As Variant
Dim i As Long
Dim str() As String
Dim j As Integer
Dim ws As Worksheet
Dim tws As Worksheet
Dim rng As Range
Set tws = Sheets("Sheet2") 'This sheet is where the lookup list is located
Set ws = Sheets("Sheet1") ' this is the list of names
Set rng = tws.Range("A1", tws.Cells(tws.Rows.Count, 1).End(xlUp))
inarr = ws.Range("A1", ws.Cells(ws.Rows.Count, 1).End(xlUp)).Value
ReDim oarr(1 To UBound(inarr, 1), 1 To 1)
For i = 1 To UBound(inarr, 1)
str = Split(inarr(i, 1), "-")
For j = 0 To UBound(str)
Dim fnd
fnd = Application.Match(str(j), rng, 0)
If Not IsError(fnd) Then
oarr(i, 1) = rng(fnd)
Exit For
End If
oarr(i, 1) = "None"
Next j
Next i
ws.Range("B1").Resize(UBound(oarr, 1)).Value = oarr
End Sub
您可以通过不多次读取值来优化您的代码,例如
Sheets("B").Cells(k, 1).Value
被多次读取,每次扫描一次将其读入变量,您也可以使用其他值进行读取。
作为替代策略,请查看 excel 搜索和查找功能
如果各个值都是 3 个字母,则类似于:
=MID(C3,SMALL(IFERROR(SEARCH($F:$F,C3),200),1),3)
使用 Ctrl+Shift+Enter
作为数组公式输入
我在 sheet 的列中有一个字符串列表(假设是 "A"),如下所示:
A
BJS-LAX-GRU
CAN-ORD-MIA-BOG
NRT-LAX-JFK-LIM
然后我在另一个 sheet 上有一个不同的列表(比如说 "B"),像这样:
A
LAX
MEX
MIA
JFK
所以我想知道第二个列表的哪个值首先出现在第一个列表的每个字符串中,然后我需要将该值写在字符串旁边。在这个例子中,我会得到:
A B
BJS-LAX-GRU LAX
CAN-ORD-MIA-BOG MIA
NRT-LAX-JFK-LIM LAX
我写了下面的代码,效果很好:
Dim aux As Integer
Dim cur As String
For j = 1 To Sheets("A").Cells(Rows.Count, "A").End(xlUp).Row
aux = 100
cur = ""
For k = 1 To Sheets("B").Cells(Rows.Count, "A").End(xlUp).Row
If InStr(Sheets("A").Cells(j, 1).Value, Sheets("B").Cells(k, 1).Value) < aux And InStr(Sheets("A").Cells(j, 1).Value, Sheets("B").Cells(k, 1).Value) <> 0 Then
cur = Sheets("B").Cells(k, 1).Value
aux = InStr(Sheets("A").Cells(j, 1).Value, cur)
End If
Next k
Sheets("A").Cells(j, 2) = cur
Next j
问题是我知道这段代码效率极低,因为这些列表有 20 万多行。有没有更有效的方法来做到这一点?
通过将值放入数组并使用 Application.Match 查找匹配项,这应该非常快:
Sub findmatch()
Dim inarr() As Variant
Dim oarr() As Variant
Dim i As Long
Dim str() As String
Dim j As Integer
Dim ws As Worksheet
Dim tws As Worksheet
Dim rng As Range
Set tws = Sheets("Sheet2") 'This sheet is where the lookup list is located
Set ws = Sheets("Sheet1") ' this is the list of names
Set rng = tws.Range("A1", tws.Cells(tws.Rows.Count, 1).End(xlUp))
inarr = ws.Range("A1", ws.Cells(ws.Rows.Count, 1).End(xlUp)).Value
ReDim oarr(1 To UBound(inarr, 1), 1 To 1)
For i = 1 To UBound(inarr, 1)
str = Split(inarr(i, 1), "-")
For j = 0 To UBound(str)
Dim fnd
fnd = Application.Match(str(j), rng, 0)
If Not IsError(fnd) Then
oarr(i, 1) = rng(fnd)
Exit For
End If
oarr(i, 1) = "None"
Next j
Next i
ws.Range("B1").Resize(UBound(oarr, 1)).Value = oarr
End Sub
您可以通过不多次读取值来优化您的代码,例如
Sheets("B").Cells(k, 1).Value
被多次读取,每次扫描一次将其读入变量,您也可以使用其他值进行读取。
作为替代策略,请查看 excel 搜索和查找功能
如果各个值都是 3 个字母,则类似于:
=MID(C3,SMALL(IFERROR(SEARCH($F:$F,C3),200),1),3)
使用 Ctrl+Shift+Enter