programing

문자열 배열의 값 일치

easyjava 2023. 6. 13. 22:53
반응형

문자열 배열의 값 일치

문제:1d 배열에 정확한 일치 값이 있는지 여부를 찾는 더 효율적인 방법을 찾고 있습니다. 기본적으로 부울 값입니다.true/false.

제가 뭔가 명백한 것을 간과하고 있나요?아니면 컬렉션 개체나 사전을 사용해야 할 때 배열을 사용하여 잘못된 데이터 구조를 사용하는 것일까요?후자에서 나는 확인할 수 있었습니다..Contains또는.Exists각각의 방법

Excel에서 다음과 같은 벡터 배열의 값을 확인할 수 있습니다.

If Not IsError(Application.Match(strSearch, varToSearch, False)) Then
' Do stuff
End If

지수를 하며, 이은정일인반며하환, 다제따다릅니한을의음의 을 받습니다.Match이 컨텍스트에서 첫 번째 일치 값만 찾는 함수입니다.이것은 일반적으로 사용되는 방법이며, 저도 오랫동안 사용해온 방법입니다.

이것은 Excel에게 충분히 만족스러운 일입니다. 하지만 다른 애플리케이션은 어떨까요?

다른 응용 프로그램에서는 기본적으로 동일한 작업을 수행할 수 있지만 Excel 개체 라이브러리에 대한 참조를 활성화한 다음 다음과 같이 수행해야 합니다.

   If Not IsError(Excel.Application.match(...))

그러나 권한/신뢰 센터 등으로 인해 분산된 파일에서 관리하기가 어렵습니다.

필터() 기능을 사용하려고 했습니다.

 If Not Ubound(Filter(varToSearch, strSearch)) = -1 Then
    'do stuff
 End If

하지만 이 접근법의 문제는Filter정한일항배아열부닌일분반다니환합배열을항목 ( 문자열이 왜 .)(하위 문자열/부분 일치 항목을 반환하는 것이 왜 유용한지 모르겠습니다.)

은 문자 의 각 생각하기에 (로것도제생는일으적반에우각른이▁the같것▁in다습니사▁on▁even니(다▁calling▁than▁more▁i는▁(되용입▁array▁excelbersome▁--▁isthis▁isative것▁need▁to▁literally▁over'▁other로▁usederate▁it▁cum▁very▁alsolessly▁the▁value▁seems▁which▁commonly)▁think으매일▁each 이는 엑셀을 호출하는 것보다 훨씬 더 번거로워 보입니다.Match기능.

For each v in vArray
   If v = strSearch Then
    ' do stuff
   End If
Next

성능에 대해 이야기하자면, 몇 가지 테스트를 대신할 수 있는 것은 없습니다.내 경험에 비추어 볼 때.Match()는 루프를 사용하는 함수를 호출하는 것보다 최대 10배 느립니다.

Sub Tester()

    Dim i As Long, b, t
    Dim arr(1 To 100) As String

    For i = 1 To 100
        arr(i) = "Value_" & i
    Next i

    t = Timer
    For i = 1 To 100000
        b = Contains(arr, "Value_50")
    Next i
    Debug.Print "Contains", Timer - t

    t = Timer
    For i = 1 To 100000
        b = Application.Match(arr, "Value_50", False)
    Next i
    Debug.Print "Match", Timer - t

End Sub


Function Contains(arr, v) As Boolean
Dim rv As Boolean, lb As Long, ub As Long, i As Long
    lb = LBound(arr)
    ub = UBound(arr)
    For i = lb To ub
        If arr(i) = v Then
            rv = True
            Exit For
        End If
    Next i
    Contains = rv
End Function

출력:

Contains       0.8710938 
Match          4.210938 

저는 최고의 대체 솔루션을 찾곤 했습니다.그것은 간단한 발견에도 효과가 있을 것입니다.

다음 코드를 사용하여 문자열의 첫 번째 인스턴스를 찾으려면:

Sub find_strings_1()

Dim ArrayCh() As Variant
Dim rng As Range
Dim i As Integer

 ArrayCh = Array("a", "b", "c")

With ActiveSheet.Cells
    For i = LBound(ArrayCh) To UBound(ArrayCh)
        Set rng = .Find(What:=ArrayCh(i), _
        LookAt:=xlPart, _
        SearchOrder:=xlByColumns, _
        MatchCase:=False)

        Debug.Print rng.Address

    Next i
End With

End Sub

모든 인스턴스를 찾으려면 아래를 참조하십시오.

Sub find_strings_2()

Dim ArrayCh() As Variant
Dim c As Range
Dim firstAddress As String
Dim i As Integer

 ArrayCh = Array("a", "b", "c") 'strings to lookup

With ActiveSheet.Cells
    For i = LBound(ArrayCh) To UBound(ArrayCh)
        Set c = .Find(What:=ArrayCh(i), LookAt:=xlPart, LookIn:=xlValues)

        If Not c Is Nothing Then
            firstAddress = c.Address 'used later to verify if looping over the same address
            Do
                '_____
                'your code, where you do something with "c"
                'which is a range variable,
                'so you can for example get it's address:
                Debug.Print ArrayCh(i) & " " & c.Address 'example
                '_____
                Set c = .FindNext(c)

            Loop While Not c Is Nothing And c.Address <> firstAddress
        End If
    Next i
End With

End Sub

한 셀 내에 검색된 문자열의 인스턴스가 여러 개 있는 경우 FindNext의 특정 특성으로 인해 하나의 결과만 반환됩니다.

그래도 발견된 값을 다른 값으로 대체하기 위한 코드가 필요하다면 첫 번째 솔루션을 사용하겠지만, 조금 변경해야 합니다.

더 인 방법 ("▁"▁to▁((방더)▁""Application.Match) ):

저는 당신이 사용하고 있는 것보다 더 효율적인 방법은 없다고 생각합니다.Application.Match.

배열을 사용하면 요소의 인덱스를 알고 있는 경우 모든 요소에 효율적으로 액세스할 수 있습니다.요소 값으로 작업을 수행하려면(요소가 있는지 확인하더라도) 최악의 경우 어레이의 모든 요소를 스캔해야 합니다.에는 그므로최경우는이 합니다.n 비교,서 요비교, 위치n배열의 크기입니다.따라서 원소가 존재하는지 여부를 찾아야 하는 최대 시간은 입력의 크기에서 선형입니다.O(n)이는 기존 배열을 사용하는 모든 언어에 적용됩니다.

우리가 더 효율적일 수 있는 유일한 경우는 어레이가 특별한 구조를 가질 때입니다.예를 들어 배열 요소가 알파벳 순으로 정렬된 경우 모든 배열을 검색할 필요가 없습니다. 중간 요소와 비교한 다음 배열의 왼쪽 또는 오른쪽 부분과 비교합니다(이진 검색).하지만 특별한 구조를 가정하지 않고는 희망이 없습니다.

Dictionary/Collection대로 에서는 키 를 지속적으로 합니다(" 용자가지대적해요대키제액다를인공니세합사스지적속한에").O(1)) 아마도 잘 문서화되지 않은 것은 사전 요소(키 및 항목)에 대한 인덱스 액세스를 가질 수 있다는 것입니다: 요소가 입력되는 순서Dictionary 요소에 되어 있기 를 더 이 단점입니다.이들의 주요 단점은 각 요소에 대해 두 개의 개체가 저장되므로 더 많은 메모리를 사용한다는 것입니다.

비록 마리를하자면만, 하지무.If Not IsError(Excel.Application.match(...))어리석어 보입니다. 여전히 더 효율적인 방법입니다(적어도 이론적으로는).허가 문제에 관한 제 지식은 매우 제한적입니다. 프로그램에 의 호트애션에따항있다습니몇가가지상라스이플케리▁always▁are▁depending다▁some있습니▁thereation,호▁applic가 있습니다.Find함수(-)C++가지다find그리고.find_if예를 들어).

그게 도움이 되길 바랍니다!

편집

수정된 게시물과 팀의 답변을 읽고 몇 가지 생각을 덧붙이고 싶습니다.위의 텍스트는 다양한 데이터 구조의 이론적 시간 복잡성에 초점을 맞추고 있으며 구현 문제를 무시합니다.오히려 '일정한 데이터 구조(배열)가 주어지면', 존재를 확인하는 실천에서 가장 효율적인 방법은 무엇인가라는 질문의 정신이 작용했다고 생각합니다.

이를 위해, 팀의 대답은 놀라운 것입니다.

규칙 " 일반인만규은 "약적"VBA당신을 위해 그것을 할 수 있고 당신 자신이 그것을 다시 쓰지 마세요"라고 항상 진실인 것은 아닙니다.과 비교와 같은 은 "보다 더 빠를 수 . "합치" 루일하 "합치"보다 빠를 수 있습니다.VBA기능들.두 가지 흥미로운 링크가 여기와 여기에 있습니다.

언급URL : https://stackoverflow.com/questions/18754096/matching-values-in-string-array

반응형