【问题标题】:search within an array with a condition在具有条件的数组中搜索
【发布时间】:2012-05-16 02:07:58
【问题描述】:

我有两个数组要在多个级别上进行比较。两者具有相同的结构,具有 3 个“列。

第一列包含多边形的 ID,第二列是区域类型,第三列是多边形的每种区域类型的百分比。

因此,对于许多行,它将比较,例如 ID : 1 Type : aaa % : 100 但是对于某些元素,我有很多行具有相同的 ID。例如,我将有 ID 2,类型 aaa,25% --- ID 2,类型 bbb,25% --- ID 2,类型 ccc,50%。在第二个数组中,我将有 ID 2,类型 aaa,25% --- ID 2,类型 bbb,10% --- ID 2,类型 eee,38% --- ID 2,类型 fff,27 %。

这是一个视觉示例..

所以,我的函数必须比较这两个数组,如果有差异,请给我发送电子邮件。 (我不会向你展示真正的代码,因为有 811 行)。第一个“if”条件是

if array1.id = array2.id Then
if array1.type = array2.type Then
if array1.percent = array2.percent Then
zone_verification = True
Else
zone_verification = False

问题是因为每个数组中有超过 50 000 行。因此,当我运行该函数时,对于每个“array1.id”,该函数在 array2 中搜索 50 000 行。 50 000 次搜索 50 000 行.. 运行时间相当长!

我正在寻找让它运行得更快的东西。我怎样才能让我的搜索更具体。示例:我在 array1 中有很多 id "2"。如果array2中有许多id“2”,找到它,并将所有array2.id = 3推入“子数组”或类似的东西,并在这些特定行中搜索。所以我将在array1中只有X行与array 2中的X行进行比较,而不是50 000。当array1中的每个“id 2”完成时,对“id 4”做同样的事情......和“ id 5"...

希望很清楚。这几乎是我第一次使用 VB.net,而且我有这么大的功能可以运行。

谢谢

编辑

这就是我想做的。

我在地理空间数据库中有两个不同的层。两层具有相同的结构。它们是地块 (55 000) 和土地利用层的“空间连接”。第一层是当前层,第二层是我们将在 2015 年之后使用的下一层。

所以我有,对于每个“地块”,每个土地使用的百分比。因此,对于“地块”(ID 7580-80-2532),我可以拥有 50% 的农业使用(TYPE FAR-23)和 50% 的住宅使用(RES-112)。在第一个数组中,我'将有 2 行具有相同的 ID (7580-80-2532),但每一行都有不同的类型 (FAR-23、RES-112) 和不同的 %。 在第二层,市政区划(土地使用)也发生了变化。因此,相同的“地块”现在将占住宅用途 (RES-112) 的 40%、商业用途 (COM-54) 的 20% 和新农业用途 (FAR-33) 的 40%。 所以,我想知道是否有一些差异。一些地块将完全相同。一些地块将保持相同的土地用途,但每个地块的百分比不同。但对于某些地块,土地利用类型或多或少,各占不同的百分比。

我希望此脚本比较这两个图层,并在同一地块 ID 的这两个图层之间存在差异时向我发送电子邮件。

脚本已经在运行,但是需要花费太多时间。

问题是,我认为,脚本遍历数组 1 中每一行的所有数组 2。

我想要的是当array1中有超过1行具有相同ID时,两个数组中都只取这个ID。

也许如果我按 ID 排序,我可以写一个条件。有点像“当你找到你要找的东西时,当你找到不同的值时停止搜索?

很难解释清楚,因为我从上周开始就一直在使用 VB。而且英语不是我的第一语言! ;)

【问题讨论】:

  • 数据是否以任何特定方式组织(即排序)?
  • 不,它没有以任何方式排序。我没有写代码。我得到了这份新工作,我的老板问我.. 让它工作得更快.. yuk

标签: vb.net arrays search


【解决方案1】:

如果你只是想知道第一个和第二个数组之间是否有任何区别,你可以这样做:

Dim diff = New HashSet(of Polygon)(array1)
diff.SymmetricExceptWith(array2)

diff 将包含任何对 array1 或 array2 唯一的多边形。如果你想做其他类型的比较,也许你应该解释一下你正在尝试做什么。

更新:

您可以像这样使用分组和查找:

'Create lookup with first array, for fast access by ID
Dim lookupByID = array1.ToLookup(Function(p) p.id)

'Loop through each group of items with same ID in array2
For Each secondArrayValues in array2.GroupBy(Function(p) p.id)

    Dim currentID As Integer = secondArrayValues.Key 'Current ID is the grouping key

    'Retrieve values with same ID in array1
    'Use a hashset to easily compare for equality
    Dim firstArrayValues As New HashSet(of Polygon)(lookupByID(currentID))

    'Check for differences between the two sets of data, for this ID
    If Not firstArrayValues.SetEquals(secondArrayValues) Then

        'Data has changed, do something
        Console.WriteLine("Differences for ID " & currentID)
    End If
Next

【讨论】:

  • 我将对其进行测试并提供一些消息,如果它有效或无效!谢谢!
【解决方案2】:

我根据您写的第一部分(即没有编辑部分)回答这个问题。正确答案应该解释一个好的算法,但我建议您使用 DB 功能,因为它们已经为此目的优化了许多查询。

将所有记录放在 DB 两个表中 - O(n) 时间...如果记录是静态的,则不需要每次都执行此步骤。 表格1 id类型百分比

表 2 id类型百分比

然后使用数据库查询,类似这样的东西 从 table1 t1、table2 t2 中选择 count(*) 其中 t1.id!=t2.id 和 t1.type!=t2.type (你可以使用一些更好的查询,我想说的是把控制权交给数据库来执行这个操作) 在您的代码中检索结果并执行必要的操作。

编辑 1)您可以在O(n logn)时间内根据ID + type + Percent对它们进行排序,然后执行二进制搜索。 2) 使用适当的键将第一条记录存储在哈希映射中 - 可以是仅 ID 或 ID+类型 这将花费 O(n) 时间,如果密钥正确,搜索将花费恒定时间。

【讨论】:

    【解决方案3】:

    您需要定义一个结构来存储这些数据。我们将所有数据存储在LandParcel 类中,该类将具有HashSet<ParcelData>

    public class ParcelData
    {
        public ParcelType Type { get; set; } // This can be an enum, string, etc.
        public int Percent { get; set; }
    
        // Redefine Equals and GetHashCode conveniently
    }
    
    public class LandParcel
    {
        public ID Id { get; set; } // Whatever the type of the ID is...
        public HashSet<ParcelData> Data { get; set; }
    }
    

    现在你必须构建你的数据结构,像这样:

    Dictionary<ID, LandParcel> data1 = new ....
    
    foreach (var item in array1)
    {
        LandParcel p;
    
        if (!data1.TryGetValue(item.id, out p)
            data1[item.id] = p = new LandParcel(id);
    
        // Can this data be repeated?
        p.Data.Add(new ParcelData(item.type, item.percent)); 
    }
    

    您对第二个数组的 data2 字典执行相同操作。现在您迭代 data1 中的所有项目,并将它们与 data2 具有相同 id 的项目进行比较。

    foreach (var parcel2 in data2.Values)
    {
         var parcel1 = data1[parcel2.ID]; // Beware with exceptions here !!!
    
         if (!parcel1.Data.SetEquals(parcel2.Data))
             // You have different parcels
    } 
    

    (现在我看了一下,我们实际上是在这里做一个小型数据库查询,有点臭代码......)

    对于 C# 代码感到抱歉,因为我对 VB 不太满意,但它应该相当简单。

    【讨论】:

    • 我不确定是否可以比较两个数组中的位置,因为数组 1 中可以有 3 行 ID 为 3,而数组 2 中可以有 5 行 ID 为 3。它们不是相等的序列.. :(
    • 然后我根本不明白这个问题:(,对不起。我认为关键是要确定两组是否不相等。现在,阅读您的编辑,我认为您必须存储数据结构比数组更好。我将编辑我的答案。
    • 正如我现在所看到的,这与@Meta-Knight 之前的回答非常相似。希望它能澄清一些事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-05
    • 2020-08-20
    • 1970-01-01
    • 2019-02-04
    • 2023-04-07
    • 2016-02-07
    • 1970-01-01
    相关资源
    最近更新 更多