gpt4 book ai didi

arrays - 来自一维数组的唯一值,无需迭代

转载 作者:行者123 更新时间:2023-12-03 18:34:43 25 4
gpt4 key购买 nike

冒着成为话题的风险,我决定分享一些代码,Q&A-style .如果普遍认为这将是题外话,如果需要,我很乐意删除。

背景

我们可以从任何一维数组中检索所有唯一值吗,或者 Range对象变成一维数组,而不必迭代其元素?就我而言,普遍的共识是必须迭代不同的元素,最好的方法是使用字典或集合来存储唯一值。Here是我发现为此目的非常有效的方法。

问题

那么如何从一维数组中检索唯一元素,例如:

Dim arr As Variant: arr = Array("A", "A", "C", "D", "A", "E", "G")

结果数组在哪里:
{"A", "C", "D", "E", "G"}

最佳答案

真正需要的所有代码都只是几行:

Sub test()

Dim arr As Variant: arr = Array("A", "A", "C", "D", "A", "E", "G")
With Application
uniques = .Index(arr, 1, Filter(.IfError(.Match(.Transpose(.Evaluate("ROW(1:" & UBound(.Match(arr, arr, 0)) & ")")), .Match(arr, arr, 0), 0), "|"), "|", False))
End With

End Sub

上面将返回一个一维数组,返回原始数组中的所有唯一元素:

enter image description here

说明:

检索所有这些值的行看起来很密集,所以让我们把它分成几部分:

enter image description here
Application.Match能够在其参数中使用数组。所以基本上我们在看: .Match({"A","A","C","D","A","E","G"},{"A","A","C","D","A","E","G"},0) .返回的数组将是: {1,1,3,4,1,6,7} ,而这实际上是找到每个值的第一个位置。这一结果将成为我们进一步发展的基础。

enter image description here

我们可以看到第三个 .Match在我们的代码中,我们基本上需要告诉以下内容: .Match({1,2,3,4,5,6,7},{1,1,3,4,1,6,7},0) .第一个参数是上面突出显示的代码检索的内容。

在哪里 .Evaluate("ROW(1:" & UBound(.Match(arr, arr, 0)) & ")")将从 1-7 返回一个值数组, Application.Transpose将返回它,使其成为一维数组。

enter image description here

最后一步将返回一个包含错误的数组,但是代码不会中断,因为我们使用的是 Application而不是 WorksheetFunction .结果数组看起来像 {1,Error 2042,3,4,Error 2042,6,7} .现在重点是摆脱 Error值(value)观。

方法是通过 Application.IfError ,它将评估数组并将所有错误值更改为给定的字符串值。在我们的例子中,我使用了管道符号。由用户决定一个足够独特的符号,它不会出现在原始数组的任何元素中。所以经过评估。我们当前的数组看起来像: {1,|,3,4,|,6,7} .

enter image description here

现在我们检索了一个带有管道符号的数组,我们希望它们出来!一个快速的方法是使用 Filter功能。 Filter返回一个包含或不包含符合我们标准的元素的数组(取决于它的第三个参数中的 TRUEFALSE)。

所以基本上我们想要返回一个像这样的数组: Filter(<array>, "|", False) .生成的一维数组现在看起来像: {1,3,4,6,7} .

enter image description here

在这一点上,我们有点。我们只需要从原始数组中切出正确的值。为此,我们可以使用 Application.Index .我们只想告诉 .Index我们对哪些行感兴趣。为此,我们可以加载我们之前找到的一维数组。所以代码看起来像: .Index(arr1, <array>, 1)这将产生一维数组: {"A","C","D","E","G"}
结论:

你有它。一行(不仅仅是一个操作)从另一个一维数组中检索一维数组的唯一值 没有 迭代。此代码可用于任何用 arr 声明的一维数组.

有用吗?我不是 100% 确定,但我终于达到了我在项目中尝试的目标。生成的数组可以立即用于您需要在其中使用唯一值的任何任务。

比较:字典与应用程序。方法:

Range(A1:A50000) 中的随机项目进行比较,性能真的很受打击。特此迭代字典与非迭代字典之间的时间比较 Application.Methods以 1000 个项目步骤逼近。在 1000 项和每 10000 项标记的结果下方(以秒为单位):
| Items     | Dictionary    | Methods       |
|------- |------------ |------------- |
| 1000 | 0,02 | 0,03 |
| 10000 | 0 | 0,88 |
| 20000 | 0,02 | 3,31 |
| 30000 | 0,02 | 7,3 |
| 40000 | 0,02 | 12,84 |
| 50000 | 0,03 | 20,2 |
Dictionary使用的方法:

Sub Test()

Dim arr As Variant: arr = Application.Transpose(Range("A1:A50000"))
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")

Dim x As Long

For x = LBound(arr) To UBound(arr)
dict(arr(x)) = 1
Next x

Dim uniques As Variant: uniques = dict.Keys

End Sub


结论:与更常见的 Dictionary 相比,此方法最多可处理 1000 个项目,处理时间大致相同。实践。在任何更大的事情上,迭代(通过内存)总是会击败方法方法!

我敢肯定,使用新的动态数组函数 shown 处理时间会受到更多限制。通过@ScottCraner。

关于arrays - 来自一维数组的唯一值,无需迭代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59683363/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com