如何判断两个数组是否共享相同的元素

发布于 2024-09-06 02:10:39 字数 135 浏览 4 评论 0原文

所以这是我的问题的一种更简单的形式。 假设我有 2 个数组。 A={1,2} 且 B={2,4,6}。 如果 A 和 B 共享一个元素,则从 B 中删除该元素。 我知道您可以循环遍历并将 A 中的每个元素与 B 中的每个元素进行比较,但必须有更好的方法!

So this is a simpler form of my problem.
Lets say I have 2 arrays. A= {1,2} and B={2,4,6}.
If A and B share an element then delete that element from B.
I know you can loop through and compare each element in A to each element in B, but there's got to be a better way!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

爱格式化 2024-09-13 02:10:39

如果您的数组已排序(或者您可以对数组进行排序),则您可以同时处理两个数组。 其各自数组的末尾之外:

  • 从两个数组的开头开始,直到将其中一个指针前进到 b 则将 a 指针前移
  • 则删除 b 处的元素
  • 如果 a = b 则删除 b 处的元素如果 a > b然后前进b指针

If your arrays are sorted (or you can sort the arrays), you can then work through both arrays simultaneously. Starting at the beginning of both arrays and going until you would advance one of the pointers beyond the end of its respective array:

  • If a < b then advance the a pointer
  • If a = b then delete the element at b
  • If a > b then advance the b pointer
花伊自在美 2024-09-13 02:10:39

您必须编写代码,但它不必是强力的双重嵌套循环,并且您不必从数组中删除单个元素。

如果添加对 Microsoft 脚本运行时的引用(从 VBE 中的“工具”菜单),则可以使用“字典”对象来简化此操作。它有“Exists”、“Remove”和“Keys”方法。因此,您可以循环遍历 B 并将元素添加为字典中的键,然后循环遍历 A,检查这些元素是否存在,如果存在,则删除它们。

作为伪代码:

for each elem in b
    dict(elem)=0 
next elem

for each elem in a
    if dict.exists(elem)
        dict.remove(elem)
    end if
next elem

return dict.keys

上述方法还会从 B 中删除重复项(如果有)。

如果您知道数组没有错误值作为元素,则还可以使用 MATCH(以及在 VBA 'Application.Match' 或 'Application.WorksheetFunction.Match' 中)。执行类似操作

=MATCH({2,4,6},{1,2},0)

将返回 {2,#N/A,#N/A}。任何带有 #N/A 的位置都是 B 中不在 A 中的元素的位置。如果您在工作表中进行匹配,则可以拖动类似的公式

=IF(ISNA(cell of match),corresponding cell of B,NA())

,然后从中过滤掉 #N/As。在VBA中,你可以这样做(更多伪代码):

matches=application.match(b,a,0) 

for each elem in matches
    if iserror(elem)
        add corresponding element of b to result
    end
next elem

redim result to new smaller size

return result

当然,然后你必须担心数组起始边界等。

You have to write code, but it doesn't have to be a brute-force doubly nested loop and you don't have to do any messy removal of individual elements from arrays.

If you add a reference to the Microsoft Scripting Runtime (from the Tools menu in the VBE), you can use a Dictionary object to make this easier. It has methods for 'Exists', 'Remove', and 'Keys'. So you could loop through B and add the elements as keys in the Dictionary, and then loop through A, checking to see if those elements exist, and if so, removing them.

As pseudocode:

for each elem in b
    dict(elem)=0 
next elem

for each elem in a
    if dict.exists(elem)
        dict.remove(elem)
    end if
next elem

return dict.keys

The above approach also removes duplicates from B if there are any.

If you know your arrays don't have error values as elements, you can also use MATCH (and in VBA 'Application.Match' or 'Application.WorksheetFunction.Match'). Doing something like

=MATCH({2,4,6},{1,2},0)

will return {2,#N/A,#N/A}. Any position with #N/A is the position of an element of B that wasn't in A. If you do the match in the worksheet, you can then drag a formula like

=IF(ISNA(cell of match),corresponding cell of B,NA())

and then filter out the #N/As from that. In VBA, you could do (more pseudocode):

matches=application.match(b,a,0) 

for each elem in matches
    if iserror(elem)
        add corresponding element of b to result
    end
next elem

redim result to new smaller size

return result

Of course, then you have to worry about array starting bounds, etc.

你对谁都笑 2024-09-13 02:10:39

基于 jtolle 伪代码的完整且解释的 VBA 解决方案

    Sub ExampleCall()
    Dim a, b: a = Array(1, 2): b = Array(2, 4, 6)
    Debug.Print "Array b: {" & Join(b, ",") & "}";  ' show original array b
    
    '~~~~~~~~~~~~~~~~~~~~~~~~
    'remove duplicates from b via Application.Index()
    '~~~~~~~~~~~~~~~~~~~~~~~~
    b = getUniques(a, b)                            ' << help function getUniques()
    
    Debug.Print " ~~> {" & Join(b, ",") & "}"       ' Array b: {2,4,6} ~~> {4,6}
    End Sub

通过 1 行 Application.Match() 帮助函数 getUniques()< /strong>

//编辑 2020-07-24 根据 @jtolle 的评论更正了数组边界:

    Function getUniques(a, b)
    'Purpose: get 1-based items of array b not matching with array a items
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    'a) match array b items against array a
    '   results in a 1-based array {2,#N/A,#N/A}, where
    '   the 1st numeric element of b equalling 2 indicates to be the 2nd item of b and
    '   error elements indicate unique items in b with no duplicate in b
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Dim matches: matches = Application.Match(b, a, 0)   ' results in 1-based array with b dimensions
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    'b) get 1-based unique items in array b
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Dim i As Long, ii As Long                           ' counters
    For i = 1 To UBound(matches)                        ' loop through matches
        If IsError(matches(i)) Then                     ' no match #N/A indicates unique item in b
            ii = ii + 1                                 ' increment new counter
            ''matches(ii) = b(i - IIf(LBound(b), 0, 1)) ' OP: get b items to maintain
              matches(ii) = b(i + LBound(b) - 1)        ' edited: get b items to maintain

        End If
    Next i
    ''ReDim Preserve matches(LBound(b) To ii - IIf(LBound(b), 0, 1)) ' OP: reduce to needed size and original boundaries
    ReDim Preserve matches(LBound(b) To ii + LBound(b) - 1) ' edited; reduce to needed size and original boundaries

    getUniques = matches                                ' return function result

    End Function

A completed and explained VBA solution based on jtolle's pseudo code

    Sub ExampleCall()
    Dim a, b: a = Array(1, 2): b = Array(2, 4, 6)
    Debug.Print "Array b: {" & Join(b, ",") & "}";  ' show original array b
    
    '~~~~~~~~~~~~~~~~~~~~~~~~
    'remove duplicates from b via Application.Index()
    '~~~~~~~~~~~~~~~~~~~~~~~~
    b = getUniques(a, b)                            ' << help function getUniques()
    
    Debug.Print " ~~> {" & Join(b, ",") & "}"       ' Array b: {2,4,6} ~~> {4,6}
    End Sub

Help function getUniques() via 1-line Application.Match()

//Edit 2020-07-24 corrected array boundaries due to @jtolle 's comment:

    Function getUniques(a, b)
    'Purpose: get 1-based items of array b not matching with array a items
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    'a) match array b items against array a
    '   results in a 1-based array {2,#N/A,#N/A}, where
    '   the 1st numeric element of b equalling 2 indicates to be the 2nd item of b and
    '   error elements indicate unique items in b with no duplicate in b
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Dim matches: matches = Application.Match(b, a, 0)   ' results in 1-based array with b dimensions
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    'b) get 1-based unique items in array b
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Dim i As Long, ii As Long                           ' counters
    For i = 1 To UBound(matches)                        ' loop through matches
        If IsError(matches(i)) Then                     ' no match #N/A indicates unique item in b
            ii = ii + 1                                 ' increment new counter
            ''matches(ii) = b(i - IIf(LBound(b), 0, 1)) ' OP: get b items to maintain
              matches(ii) = b(i + LBound(b) - 1)        ' edited: get b items to maintain

        End If
    Next i
    ''ReDim Preserve matches(LBound(b) To ii - IIf(LBound(b), 0, 1)) ' OP: reduce to needed size and original boundaries
    ReDim Preserve matches(LBound(b) To ii + LBound(b) - 1) ' edited; reduce to needed size and original boundaries

    getUniques = matches                                ' return function result

    End Function

冷情 2024-09-13 02:10:39

不,我认为没有。你必须循环遍历。

No there is not I think. You have to loop through.

蓝礼 2024-09-13 02:10:39

如果数组内的值对于其数组来说是唯一的,则可以使数组索引实际值,从而允许您直接查找其索引,而不是扫描整个数组。

从元素较少的数组开始,我假设您想要执行 excel/VB?我制作了一张图片来说明这个想法。

http://img694.imageshack.us/img694/1503/hackmap.jpg

您没有两个嵌套循环,而是一个循环,并且它仅迭代与最小数组一样多的次数。

If values inside a array are unique for its array, you could make the array indexes the actual values, allowing you to seek directly to its index, instead of scanning the entire array.

Start with the array that has fewer elements, and i assume you are wanting to do excel/VB? I made a picture to illustrate the idea.

http://img694.imageshack.us/img694/1503/hackmap.jpg

Instead of having two nested loops, you have one loop, and it only iterates as many times as the smallest array.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文