Удаление повторяемых строчных элементов в массиве

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Citius
Обычный пользователь
Обычный пользователь
 
Сообщения: 74
Зарегистрирован: 09.11.2005 (Ср) 9:36
Откуда: Украина

Удаление повторяемых строчных элементов в массиве

Сообщение Citius » 27.06.2007 (Ср) 0:00

Код: Выделить всё
    For i = 1 To UBound(Txt)
        For j = 1 To UBound(Txt)
        If i <> j Then
            If Txt(i) = Txt(j) Then
                For k = 1 To UBound(KeyW)
                    If KeyW(k) = Txt(i) Then
                        Countt = 1
                    End If
                Next k
                If Countt <> 1 Then
                    Count = Count + 1
                    ReDim Preserve KeyW(1 To Count)
                    KeyW(Count) = Txt(i)
                    KeyWords = KeyWords & KeyW(Count) & " "
                   
                End If
                Countt = 0
            End If
        End If
        Next j
    Next i


Что скажете про вот такой вот способ избавится от повторения одинаковых слов в массиве?
Как можно улучшить код? И стоит ли это делать?[/code]

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 27.06.2007 (Ср) 0:32

Скажем, что коллекции рулят.
Кстати: у тебя слова, отличающиеся регистром, будут считаться различными. Это намеренно?
Изображение

EUGY
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 214
Зарегистрирован: 09.11.2006 (Чт) 22:51
Откуда: Мурманск

Сообщение EUGY » 27.06.2007 (Ср) 6:18

Смотря для чего это надо.
можно например сначала проделать сортировку,
а потом уже одним прогоном цикла убрать не нужное.
Очень не нравится Redim во вложенных циклах.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 27.06.2007 (Ср) 10:16

А с коллекциями даже сортировка не нужна...
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 27.06.2007 (Ср) 10:40

С коллекциями нужно делать специальный класс с одним лишь свойством (стринговым), которое будет свойством по умолчанию.

С Dictionary ничего такого не нужно.

ЗЫ. Появилась идея написать кирпич "PHP-подобные переменные и массивы"
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 27.06.2007 (Ср) 11:00

Нафига для коллекции делать класс?
Что, я обычные строки не могу в коллекцию положить?
Изображение

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 27.06.2007 (Ср) 11:08

Строки нет, Variant можешь.
Вернее, положить сможешь, забрать же только в Variant.
Lasciate ogni speranza, voi ch'entrate.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 27.06.2007 (Ср) 12:13

С таким уровнем придирок, я и написанный Хакером класс не смогу положить ;-)
Изображение

Citius
Обычный пользователь
Обычный пользователь
 
Сообщения: 74
Зарегистрирован: 09.11.2005 (Ср) 9:36
Откуда: Украина

Сообщение Citius » 28.06.2007 (Чт) 0:27

tyomitch писал(а):Скажем, что коллекции рулят.
Кстати: у тебя слова, отличающиеся регистром, будут считаться различными. Это намеренно?


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

Citius
Обычный пользователь
Обычный пользователь
 
Сообщения: 74
Зарегистрирован: 09.11.2005 (Ср) 9:36
Откуда: Украина

Сообщение Citius » 28.06.2007 (Чт) 0:30

EUGY писал(а):Очень не нравится Redim во вложенных циклах.


Объясни пожалуйста, почему? Как это влияет на работу программы?

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 28.06.2007 (Чт) 7:35

Citius
ReDim замедляет работу. А во вложенном цикле - замедляет множество раз.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 28.06.2007 (Чт) 8:21

Citius писал(а):
tyomitch писал(а):Скажем, что коллекции рулят.
Кстати: у тебя слова, отличающиеся регистром, будут считаться различными. Это намеренно?


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

Ну тогда ещё лучше: коллекция сама отслеживает уникальность без учёта регистра.
Тебе даже не придётся переводить строки в нижний регистр самому.
Изображение

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Сообщение SSecurity » 08.07.2007 (Вс) 14:15

Против редима я ничего не имею ...
Но предложенный код бы составил так

Код: Выделить всё
Dim KeyW() as string
Redim KeyW(0)
Count = 0
For i = 1 To UBound(Txt)
  If Txt(i)<>"" then
    For j = 1 To UBound(Txt)
      If i <> j Then
        '## убъем все похожие слова на корню, чтобы не мешали
        If Txt(i) = Txt(j) Then Txt(j) = ""
      Next j
    End if
    Count = Count + 1
    Redim Preserve KeyW(Count) 
    KeyW(Count) = Txt(I)
  End if
Next i


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

С Уважением,
Сергей
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Сообщение SSecurity » 08.07.2007 (Вс) 14:23

Ну или в крайнем случае можешь редим не делать .... а после исполнения кода .... в массиве останутся только уникальные слова ... т.е. простоым перебором и исключением пустых строк получишь нужный тебе массив уникальностей.

С Уважением,
Сергей
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 08.07.2007 (Вс) 15:21

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

И в чём преимущество кода без коллекций?
Изображение

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Сообщение SSecurity » 08.07.2007 (Вс) 15:42

По моему мнению
При небольших размерах массива (до сотни) перебор будет быстрее.
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 08.07.2007 (Вс) 16:02

А в сто раз медленнее не хочешь? ;-)

Код: Выделить всё
Option Explicit

Const Sample = "Twas brillig and the slithy toves " & _
               "Did gyre and gimble in the wabe " & _
               "All mimsy were the borogoves " & _
               "And the mome raths outgrabe " & _
               "Beware the Jabberwock my son " & _
               "The jaws that bite the claws that catch " & _
               "Beware the Jubjub bird and shun " & _
               "The frumious Bandersnatch " & _
               "He took his vorpal sword in hand " & _
               "Long time the manxome foe he sought " & _
               "So rested he by the Tumtum tree " & _
               "And stood awhile in thought " & _
               "And as in uffish thought he stood " & _
               "The Jabberwock with eyes of flame " & _
               "Came whiffling through the tulgey wood " & _
               "And burbled as it came" '95 слов

Sub Main()
Dim test1() As String, test2() As String, Start As Double
test1 = Split(Sample)
test2 = test1

Start = Timer
Debug.Print Join(SSecurity(test1))
Debug.Print Timer - Start

Start = Timer
Debug.Print Join(tyomitch(test2))
Debug.Print Timer - Start
End Sub

Private Function SSecurity(Txt() As String) As String()
ReDim KeyW(0) As String
Dim Count As Long, i As Long, j As Long
Count = 0
For i = LBound(Txt) To UBound(Txt)
  If Txt(i) <> "" Then
    For j = LBound(Txt) To UBound(Txt)
      If i <> j Then
        '## убъем все похожие слова на корню, чтобы не мешали
        'tyomitch: для справедливости добавил приведение регистров
        If LCase(Txt(i)) = LCase(Txt(j)) Then Txt(j) = ""
      End If
    Next j
    Count = Count + 1
    ReDim Preserve KeyW(Count)
    KeyW(Count) = Txt(i)
  End If
Next i
SSecurity = KeyW
End Function

Private Function tyomitch(Txt() As String) As String()
Dim c As Collection: Set c = New Collection
On Error Resume Next
Dim i: For Each i In Txt
    c.Add i, i
Next
ReDim Result(1 To c.Count) As String
Dim j As Long: j = 1
For Each i In c
    Result(j) = i
    j = j + 1
Next
tyomitch = Result
End Function


На моём прогоне получаются 1,63E-02 и 3,75E-04 секунд, соответственно.
Изображение

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Сообщение SSecurity » 08.07.2007 (Вс) 20:03

S: 7,24999999947613E-02
T: 1,03125000023283E-02

(ну не вижу тут я 100 кратного опережения)

Это получилось у меня ... Когда я лишь твой СИМПЛ сделал Стрингом, и просто в МАЙНе твой массив поместил.

А после того как я предварительно провел операцию LCase со всему исходному массиву, как это у автора топика и происходит, то вообще получил

S: 1,83125000039581E-02
T: 1,95625000051223E-02

S: 4,63750000053551E-02
T: 6,66875000024447E-02

(а здесь и поспорить можно) ...

Все говорит о том, что все зависит от кокретных условий:)

С Уважением,
Сергей
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Сообщение SSecurity » 08.07.2007 (Вс) 20:04

Код: Выделить всё
Option Explicit

Dim Sample As String


Sub Main()
Dim test1() As String, test2() As String, Start As Double

Sample = "Twas brillig and the slithy toves " & _
               "Did gyre and gimble in the wabe " & _
               "All mimsy were the borogoves " & _
               "And the mome raths outgrabe " & _
               "Beware the Jabberwock my son " & _
               "The jaws that bite the claws that catch " & _
               "Beware the Jubjub bird and shun " & _
               "The frumious Bandersnatch " & _
               "He took his vorpal sword in hand " & _
               "Long time the manxome foe he sought " & _
               "So rested he by the Tumtum tree " & _
               "And stood awhile in thought " & _
               "And as in uffish thought he stood " & _
               "The Jabberwock with eyes of flame " & _
               "Came whiffling through the tulgey wood " & _
               "And burbled as it came" '95 ñëîâ

Sample = LCase(Sample)
test1 = Split(Sample)

test1 = Split(Sample)
test2 = test1

Start = Timer
Debug.Print Join(SSecurity(test1))
Debug.Print Timer - Start

Start = Timer
Debug.Print Join(tyomitch(test2))
Debug.Print Timer - Start
End Sub

Private Function SSecurity(Txt() As String) As String()
ReDim KeyW(0) As String
Dim Count As Long, i As Long, j As Long
Count = 0
For i = LBound(Txt) To UBound(Txt)
  If Txt(i) <> "" Then
    For j = LBound(Txt) To UBound(Txt)
      If i <> j Then
        '## óáúåì âñå ïîõîæèå ñëîâà íà êîðíþ, ÷òîáû íå ìåøàëè
        'tyomitch: äëÿ ñïðàâåäëèâîñòè äîáàâèë ïðèâåäåíèå ðåãèñòðîâ
        'If LCase(Txt(i)) = LCase(Txt(j)) Then Txt(j) = ""
        If Txt(i) = Txt(j) Then Txt(j) = ""
      End If
    Next j
    Count = Count + 1
    ReDim Preserve KeyW(Count)
    KeyW(Count) = Txt(i)
  End If
Next i
SSecurity = KeyW
End Function

Private Function tyomitch(Txt() As String) As String()
Dim c As Collection: Set c = New Collection
On Error Resume Next
Dim i: For Each i In Txt
    c.Add i, i
Next
ReDim Result(1 To c.Count) As String
Dim j As Long: j = 1
For Each i In c
    Result(j) = i
    j = j + 1
Next
tyomitch = Result
End Function
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 08.07.2007 (Вс) 20:09

SSecurity писал(а):А после того как я предварительно провел операцию LCase со всему исходному массиву, как это у автора топика и происходит

Нечестно: с моим вариантом этот LCase не нужен, а с твоим нужен.
Вставляй его под свой таймер ;-)
Изображение

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Сообщение SSecurity » 08.07.2007 (Вс) 20:24

А, НАХ, текст в том виде в котором он есть ... начальные условия вполне ясно были описаны ...

Я твой намек прекрасно понимаю ... конечно время возрастет если ты N раз будешь вызывать LCase :)

Сам вызов времени требует ... и ты сам это прекрасно понимаешь:)
Кроме того для сравнения можно использовать нормальную функцию сравнения
Код: Выделить всё
If StrComp(Txt(i), Txt(j), vbTextCompare) = 0 Then Txt(j) = ""

тогда если оставить массив неформатированным получим:
S: 1,61249999946449E-02
T: 1,30000000062864E-02
S: 2,89374999993015E-02
T: 2,23750000004657E-02


С Уважением,
Сергей


[/quote]
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 08.07.2007 (Вс) 20:32

SSecurity писал(а):Кроме того для сравнения можно использовать нормальную функцию сравнения
Код: Выделить всё
If StrComp(Txt(i), Txt(j), vbTextCompare) = 0 Then Txt(j) = ""

тогда если оставить массив неформатированным получим:
S: 1,61249999946449E-02
T: 1,30000000062864E-02
S: 2,89374999993015E-02
T: 2,23750000004657E-02


И где же здесь превосходство в скорости у перебора? :-)


Про стократный перевес при вызове LCase в двойном цикле -- естественно это было только поводом ;-)
Изображение

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Сообщение SSecurity » 09.07.2007 (Пн) 0:42

Вообще я речь веду о том, что перебрать массив размерностью до 100 эффективнее чем заюзать коллекцию ...

Ну и так, на всякий случай - про 100 раз это твои слова ... я лишь размерность обозначил:)

С Уважением,
Сергей
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 09.07.2007 (Пн) 8:36

SSecurity писал(а):Вообще я речь веду о том, что перебрать массив размерностью до 100 эффективнее чем заюзать коллекцию ...

А я о том, что это не так ;-)
Если при переборе сравнивать без учёта регистра, что соответствует поставленной задаче.
Изображение

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Сообщение SSecurity » 09.07.2007 (Пн) 11:07

tyomitch писал(а):
SSecurity писал(а):Вообще я речь веду о том, что перебрать массив размерностью до 100 эффективнее чем заюзать коллекцию ...

А я о том, что это не так ;-)
Если при переборе сравнивать без учёта регистра, что соответствует поставленной задаче.


Хотел матюкнуться, но передумал .... (всеравно остался при своем мнении)
Набей массив элементам и сделай функцию поиска (два варианта)
1. перебором
2. через коллекцию
И посмотри что быстрее :)
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 09.07.2007 (Пн) 11:43

Издеваешься что ли? Коллекция -- это хеш-таблица, в ней поиск за константное время.
Изображение

Citius
Обычный пользователь
Обычный пользователь
 
Сообщения: 74
Зарегистрирован: 09.11.2005 (Ср) 9:36
Откуда: Украина

Сообщение Citius » 02.08.2007 (Чт) 16:29

Сказать по правде, то мне больше подходит код с Коллекциями, т.к. переборов зачастую бывает за 1000!!!


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Google-бот, Yandex-бот и гости: 39

    TopList