Сравнение массивов в VB.NET - PullRequest
4 голосов
/ 20 мая 2009

Позвольте мне предоставить небольшую деталь, чтобы объяснить, что я пытаюсь сделать, прежде чем я начну разбираться в сути вопроса.

У меня есть два источника данных - один представляет собой SQL Server, содержащий номера деталей, описания и т. Д. Другой - это система САПР, которая в традиционном смысле не имеет базы данных. То, что я пытаюсь сделать, это прочитать спецификацию с SQL Server и сравнить ее с чертежом сборки CAD, чтобы убедиться, что система CAD содержит ту же информацию, что и SQL Server.

Получение данных с SQL Server довольно просто. Я запрашиваю базу данных и заполняю сетку данных. Готово. Быстрый. Легко.

Получение данных из системы САПР немного сложнее. Мне нужно загрузить сборочный чертеж, чтобы получить список всех составных частей, а затем загрузить эти отдельные чертежи, чтобы получить свойство «Номер детали» из чертежа. Это несколько трудоемкий и медленный процесс (к сожалению), так как каждый из файлов должен быть доступен. Я загружаю эти свойства в массив (я думаю, что список может быть более эффективным).

Итак, теперь у меня есть сетка данных и массив с номерами деталей. Мне нужно сравнить их и соответственно раскрасить сетку. Сетка должна оставаться прозрачной, если деталь существует в обоих, покрасить строку в желтый, если она существует только в сетке, и добавить строку, окрашенную в красный, если только в массиве.

Насколько я могу судить, это означает циклический перебор массива в каждой строке сетки. Мыслительный процесс таков:

  1. По умолчанию для сетки заданы желтые строки.
  2. Цикл по сетке и цикл по массиву для сравнения. Если совпадение найдено, сделайте строку прозрачной и удалите элемент из массива.
  3. После выполнения шага 2 массив должен содержать только элементы, которые не найдены в сетке. Измените размер массива, чтобы удалить пустые элементы.
  4. Добавьте элементы массива в сетку и раскрасьте эти новые строки красным.

Проблемы с этой логикой в ​​том, что она кажется дорогой с точки зрения производительности. Конечно, есть лучший метод? Кроме того, если я изменю сетку каким-либо образом (например, курортом), мне придется пройти через процесс снова. Буду очень признателен за некоторые советы по этому поводу.

Спасибо!

Примечание: написано в Visual Studio 2005.

Ответы [ 4 ]

7 голосов
/ 20 мая 2009

Вы можете загрузить данные из системы CAD в словарь (проиндексированный по номеру детали). Затем вы можете просмотреть таблицу и проверить, существует ли она в словаре, что является быстрой операцией (O (1)). Вы можете сделать именно так, как вы сказали, удалить найденные элементы в словаре и добавить остальные элементы в сетку данных.

Вот некоторый код для создания и использования словаря (для сохранения форматирования использовались комментарии в стиле C #):

//First argument is your key type, second is your item type
Dim cadParts As New Dictionary(Of Integer, Part)

//Add items to the parts dictionary
For Each part As Part In cadPartsArray
  cadParts.Add(part.PartNumber,part)
Next

//Check if a part exists
Dim partNumber As Integer = 12345
If cadParts.ContainsKey(partNumber) ...

//Remove a part
cadParts.Remove(partNumber)

//Go through the remaining values
For Each part As Part In cadParts.Values ...

Edit:

1) Да, если ваш ключ (здесь, номер детали) является строкой, то будет использоваться словарь (Of String, ...).

2) Я предположил, что у вас есть класс с именем Part, который содержит некоторую информацию о детали. Если у вас есть только номер детали и никакой другой информации, вы можете вместо этого создать Hashset. По сути, это то же самое, что словарь, но с этой структурой значение также является вашим ключом. Вы могли бы создать хэш-сет как это:

Dim cadParts As New Hashset(Of String)

Я не буду разбираться с примерами кода, потому что он очень близок к Словарю. ContainsKey становится Contains, а Add принимает только один аргумент (здесь будет ваш номер детали).

3) Да, пройдитесь по ним и добавьте их в хэш-набор.

2 голосов
/ 20 мая 2009

Учитывая, что за один раз будет видно только определенное количество строк сетки данных, возможно, будет быстрее реализовать некоторый код в методе OnPaint (я немного заржавел, поэтому извиняюсь, если это не так точно) для каждой из строк, которая проверяет массив информации о деталях и устанавливает цвет фона каждой строки, когда она становится видимой, возможно, даже помечая каждую строку как обработанную, поэтому операцию не нужно повторять. Здесь может быть начальное повышение производительности по сравнению с обработкой всех строк одновременно.

Не имеет значения; но из предыдущего опыта это звучит так, будто вы взаимодействуете с файлами AutoDESK Inventor?

2 голосов
/ 20 мая 2009

Если номер детали уникален (он не повторяется в значениях, которые вы хотите найти), тогда вы можете использовать отсортированный словарь. Затем удалите дубликаты и используйте оставшиеся элементы.

Для сравнения вы можете использовать номер детали следующим образом:

if(dictionary.ContainsKey(partNumber))
    dictionary.Remove(partNumber)
end if
1 голос
/ 20 мая 2009

Другим решением может быть реализация интерфейса IComparable (Of T)

Это потребует от вас создания класса, который вы будете использовать в обеих ситуациях.

Public Class Item
    Implements IComparable(Of Item)

    Private _Description As String
    Public Property Description() As String
        Get
            Return _Description
        End Get
        Set(ByVal value As String)
            _Description = value
        End Set
    End Property

    Private _PartNo As Integer
    Public Property PartNo() As Integer
        Get
            Return _PartNo
        End Get
        Set(ByVal value As Integer)
            _PartNo = value
        End Set
    End Property

    Public Function CompareTo(ByVal other As Item) As Integer Implements System.IComparable(Of Item).CompareTo
        ' Your rules for comparing content for objects
        If other.PartNo <> Me.PartNo Then Return 1
        If other.Description <> Me.Description Then Return 1

        ' Return 0 if the object are the same
        Return 0
    End Function
End Class

Вот небольшой тест, который работает с верхней реализацией.

    Dim item As New Item
    item.Description = "Desc"
    item.PartNo = 34

    Dim item2 As New Item
    item2.Description = "Desc"
    item2.PartNo = 35

    Dim item3 As New Item
    item3.Description = "Desc"
    item3.PartNo = 36

    Dim listFromDatabase As New Generic.List(Of Item)
    listFromDatabase.Add(item)
    listFromDatabase.Add(item2)

    If listFromDatabase.Contains(item2) Then
        MessageBox.Show("item2 was found in list")
    End If

    If Not listFromDatabase.Contains(item3) Then
        MessageBox.Show("item3 was NOT found in list")
    End If

Надеюсь, это немного поможет, - Дан

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...