Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > VB .NET > Поиск в массиве


Автор: timich 5.3.2009, 03:56
Подскажите пожалуйста, как нужно искать числа в массиве.

Допустим на этом примере.

Код

 Dim массив(7) As Integer

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        массив(1) = 10
        массив(2) = 5
        массив(3) = 1
        массив(4) = 6
        массив(5) = 124
        массив(6) = 77
        массив(7) = 31

        'если в массиве есть например числа 77, 124, 5 то 

        Debug.WriteLine("есть")

    End Sub

Автор: -Mikle- 5.3.2009, 09:05
Принцип тот же:

Код

        Dim expr, find As Integer
        expr = 124
        ' одна из следующих строк, в зависимости что тебе нужно получить
        find = Array.Find(arr, Function(val As Integer) val = expr)
        find = Array.FindIndex(arr, Function(val As Integer) val = expr)
        find = Array.FindLast(arr, Function(val As Integer) val = expr)
        find = Array.FindLastIndex(arr, Function(val As Integer) val = expr)
        ' а эта строчка вернет в массиве все найденные элементы
        Dim result() As Integer = Array.FindAll(arr, Function(val As Integer) val = expr)


Подробнее тут:
http://msdn.microsoft.com/ru-ru/library/d9hy2xwa.aspx
http://msdn.microsoft.com/ru-ru/library/2857xz7b.aspx
http://msdn.microsoft.com/ru-ru/library/system.array.findindex.aspx
http://msdn.microsoft.com/ru-ru/library/system.array.findlastindex.aspx
http://msdn.microsoft.com/ru-ru/library/1kkxfxdd.aspx


Автор: diadiavova 5.3.2009, 12:43
Немного дополню ответ.
Помимо указанных функций есть ещё функция Contains, при чём есть такой метод пришедший из интерфейса System.Collections.Generic..::.ICollection<(Of <(T>)>) , что даёт возможность его использовать в начиная с 8 версии языка, но в последней версии появился такой же расширяющий метод System.Linq.Enumerable.Contains(Of TSource), который добавляется ко всем типам, реализующим интерфейс IEnumerable.
Если надо проверять наличие сразу нескольких элементов, то целесообразно использовать собственный метод-расширитель
Код

Imports System.Runtime.CompilerServices
Module Module1
    Sub Main()
        Dim arr() As Integer = {1, 23, 3, 2}
        Console.WriteLine(arr.ContainsAll(1, 2, 3))
        Console.WriteLine(arr.ContainsAll(1, 2, 5))
        Console.ReadLine()
    End Sub
End Module
Module Ext
    <Extension()> _
    Function ContainsAll(Of T)(ByVal arr() As T, ByVal ParamArray elems() As T) As Boolean
        Dim rv As Boolean = True
        For Each el As T In elems
            rv = rv And arr.Contains(el)
        Next
        Return rv
    End Function
End Module


В данном примере я добавил к массиву метод ContainsAll, который проверяет наличие всех, переданных ему, аргументов и возвращает True, если они все присутствуют в массиве, если хоть какой-нибудь отсутствует, то метод возвратит False, что и рподемострированно примером.

Автор: -Mikle- 5.3.2009, 13:00
diadiavova, очень хороший пример! (+1)  smile 

Автор: timich 5.3.2009, 13:12
Даааа... Мне это надо неделю переваривать smile 
Спасибо! Попробую разобраться.
Кстати, а на моем примере допишите нужные строки плиз.

Автор: diadiavova 5.3.2009, 14:02
Просмотрел свой пример и нашёл пару слабых мест:
1. Если методу ContainsAll не передавать аргументы, то он возвратит True, хотя, по логике вещей должно быть наоборот.
Решить проблему можно двумя способами, либо осуществлять проверку этого обстоятельства в коде, либо один аргумент сделать обязательным(этот мне нравится больше).
2.Если среди аргументов попался хотя бы один, отсутствующий в массиве, то дальнейший их перебор бессмысленен.
Приведу исправленный вариант
Код

Imports System.Runtime.CompilerServices
Module Ext
    <Extension()> _
    Function ContainsAll(Of T)(ByVal arr() As T, ByVal first As T, ByVal ParamArray elems() As T) As Boolean
        If arr.Contains(first) Then
            For Each el As T In elems
                If Not arr.Contains(el) Then
                    Return False
                End If
            Next
        Else
            Return False
        End If
        Return True
    End Function
End Module


Кроме того: есть смысл добавить его к ко всему, что реализует IEnumerable.

Цитата(timich @  5.3.2009,  13:12 Найти цитируемый пост)
Кстати, а на моем примере допишите нужные строки плиз.


Код

 Dim массив(7) As Integer
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        массив(1) = 10
        массив(2) = 5
        массив(3) = 1
        массив(4) = 6
        массив(5) = 124
        массив(6) = 77
        массив(7) = 31
        If массив.ContainsAll( 77, 124, 5 ) Then
            Debug.WriteLine("есть")
        End If
    End Sub


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

Добавлено через 6 минут и 32 секунды
Цитата(-Mikle- @  5.3.2009,  13:00 Найти цитируемый пост)
diadiavova, очень хороший пример! (+1)  smile  

Thx

Автор: -Mikle- 5.3.2009, 14:13
Цитата(timich @  5.3.2009,  16:12 Найти цитируемый пост)
Кстати, а на моем примере допишите нужные строки плиз

Лучше будет, если ты сам допишешь, так ты по крайней мере хоть немного привыкнешь.

А по поводу
Цитата(timich @  5.3.2009,  16:12 Найти цитируемый пост)
Мне это надо неделю переваривать 

то тебе дорога в МСДН, там все довольно доступно расписано про Extension методы. На самом деле это не сложнее, чем просто методы, которые ты уже знаешь...

http://msdn.microsoft.com/ru-ru/library/bb384936.aspx

Добавлено через 3 минуты и 36 секунд
Упс... опоздал...

Цитата(diadiavova @  5.3.2009,  17:02 Найти цитируемый пост)
Просмотрел свой пример и нашёл пару слабых мест

А я вот даже не стал проверять твой код, на слово поверил  smile ....  эх ты.....  smile 

Автор: diadiavova 5.3.2009, 14:18
Цитата(-Mikle- @  5.3.2009,  14:13 Найти цитируемый пост)
эх ты

Ну я же исправился smile 

Автор: timich 7.3.2009, 00:38
Все работает классно! Спасибо!
Применил пример от diadiavova, но если честно, то конечно не абсолютно все понятно, но продолжаю изучать smile 

Автор: diadiavova 7.3.2009, 00:40
А что конкретно не ясно, сам алгоритм или ещё что-то?

Автор: timich 7.3.2009, 00:56
Не понятно , например  что такое <Extension()> в принципе.

В мсдн объяснения для программистов, а не для новичков)))

Потом, что такое Т и тоже в принципе. Ради интереса пробовал менять на другую букву, не знаю зачем но так просто)))

Это тоже  ByVal ParamArray elems() As T

Вообще , не знаю плохо это или хорошо, не знакомый код несколько раз просматриваю в пошаговой работе, очень помогает.

А в алгоритме вроде бы ясно все.

Автор: diadiavova 7.3.2009, 01:19
Цитата(timich @  7.3.2009,  00:56 Найти цитируемый пост)
Не понятно , например  что такое <Extension()> в принципе.

Это новая фича в языке, позволяет дополнить любой тип своими методами. Если бы я не использовал её, то методом всё равно можно было бы пользоваться, толко так проще(не удивляйся)

Вот как выглядит твой код учитывая, что я воспользовался этим атрибутом
Код

        If массив.ContainsAll( 77, 124, 5 ) Then
            Debug.WriteLine("есть")
        End If


Если бы я этого не сделал, то код следовало бы писать так
Код

        If ContainsAll(массив, 77, 124, 5 ) Then
            Debug.WriteLine("есть")
        End If


Собственно разница именно в этом. Когда метод помечается, как расширитель, то он как бы становится членом типа. На самом деле у класса Array нет метода ContainsAll, а мы его вызываем так, как будто он у него есть. Делается это благодаря тому, что мы расширили класс своим методом.


Цитата(timich @  7.3.2009,  00:56 Найти цитируемый пост)
Потом, что такое Т и тоже в принципе. Ради интереса пробовал менять на другую букву, не знаю зачем но так просто)))

Тебе надо почитать http://msdn.microsoft.com/ru-ru/library/w256ka79.aspx. 
В общем и целом: универсальные типы удобны в тех случаях, когда заранее тип объекта неизвестен, а с ним надо работать. 
В данном случае нам известно, что мы работаем с массивом, но тип элементов массива может быть любым, и для того, чтобы как-то обращаться с этим неведомым типом мы его обозначаем буквой T. Обрати внимание, что тут нам надо было указать, что и массив и остальные параметры должны быть одного и того же типа, но не уточняется какого.




Цитата(timich @  7.3.2009,  00:56 Найти цитируемый пост)
Это тоже  ByVal ParamArray elems() As T


ParamArray указывает, что метод может принимать неопределённое количество аргументов. Обрати внимание, что здесь было передано 3 аргумента, хотя указано только 2 параметра(arr не считается). Аргументов могло быть и больше, только возникает вопрос, как обработать их все в коде. Обычно к аргументам обращаются по именам, но когда их количество неопределено, то и имена всем дать невозможно. Поэтому принята такая модель, что последний параметр метода может быть помечен словом ParamArray. Это означает, что этому параметру можно передать любое количество аргументов указанного типа, но в теле функции к ним надо обращаться как к элементам массива.


Автор: timich 7.3.2009, 05:53
Ну так намного легче  smile 
Большое спасибо!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)