在具有条件的数组中搜索

时间:2012-05-07 14:54:15

标签: vb.net arrays search

我有两个数组,我试图在很多层面进行比较。两者都具有相同的结构,有3“列。

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

因此,对于许多行,它将比较,例如,ID:1类型: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 %。

这是一个视觉示例.. PrintScreen

所以,我的功能必须比较这两个数组,如果存在差异,请给我发电子邮件。 (我不会告诉你真正的代码,因为有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行来与数组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)和不同的%。 在第二层,同样的市政区划(土地利用)已经改变。因此,相同的“地块”现在将占住宅用途的40%(RES-112),20%的商业用途(COM-54)和40%的新农业用途(FAR-33)。 所以,我想知道是否存在一些差异。一些地块将完全相同。一些包裹将保持相同的土地使用,但每个地块的百分比不同。但对于某些地块,将会有或多或少的土地利用类型,每种类型的比例不同。

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

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

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

我想要的是当array1中有多个具有相同ID的行时,在两个数组中只使用此ID。

也许如果我按ID订购,我可以写一个条件。当你找到你正在寻找的东西时,当你找到不同的价值时停止搜索?

很难解释清楚因为我上周以来一直在使用VB ..而且英语不是我的第一语言! ;)

3 个答案:

答案 0 :(得分:0)

您需要定义存储此数据的结构。我们会将所有数据存储在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 :(得分:0)

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

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

diff将包含array1或array2独有的任何Polygon。如果你想进行其他类型的比较,也许你应该解释你正在尝试做什么。

<强>更新

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

'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 :(得分:0)

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

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

表2 id type percent

然后使用数据库查询,这样的事情 从table1 t1,table2 t2中选择count(*),其中t1.id!= t2.id和t1.type!= t2.type (你可以使用一些更好的查询,我想说的是给DB控制执行此操作) 检索代码中的结果并执行必要的操作。

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