Новая тема о функциях Join и Split

Автор Tigrik, 12 июня 2020, 01:24

0 Пользователи и 1 гость просматривают эту тему.

Tigrik

Здравствуйте!

По поиску на форуме нашёл эту тему, так как моя "проблема", насколько я могу судить, очень похожая. Только не уверен, что это правильно - "залезать" в чужие темы. Если это так, тогда свой вопрос переоформлю в отдельную тему (если он того стОит).
Мои "непонятки" начались тогда, когда я попытался разложить двух-символьную строку в массив. Получилось три элемента. Когда объединяется этот массив, то получается строка из двух пробелов.
Для наглядности оформил тестовый код.

strTemp = String(2, "A") '  Получается строка - "AA"
i = Len(strTemp) '  -> 2     Все правильно - строка из двух символов
aText() = Split(strTemp, "A") '  Получается три элемента массива - Variant(0 To 2)
i = LBound(aText()) : j = UBound(aText()) '  от 0 до 2
strTemp = strTemp & chr(10)
For i = LBound(aText()) To UBound(aText()) : strTemp = strTemp + ( i & aText(i) & i  & chr(10)) : Next
Msgbox  strTemp '  Это были три пустые строки
strTemp = Join(aText()) '  Соединяем три пустые строки
i = Len(strTemp) '  -> 2     Три элемента массива образуют строку из двух символов
Msgbox  "3" & strTemp & "3" '  И это получается пробелы
aText() = Split(strTemp, " ") '  Снова получается три элемента массива - Variant(0 To 2)
i = LBound(aText()) : j = UBound(aText()) '  от 0 до 2


Вполне допускаю, что я неправильно интерпретирую, что называется "не верь глазам своим".
Скорее всего, в строке есть символ "конца строки", который и "укладывается" в последнюю "ячейку" массива.
Это всегда так, то есть, при любой строке и при любом его "расщепление" (тестил только в пределах своего "понимания" этой темы)?

---
Уже дописав сообщение, ещё раз внимательно прочёл все сообщения в этой теме. Разговор идёт о неправильных индексах в массивах при работе функции Split(), но та ли эта ситуация, что в моём случае - так и не понял.

P.S. Уже перед отправкой сообщения подумал, что Join() так и "должен" поступить - как еще определить пустой элемент - хотя бы пробелом. Но остается вопрос о дополнительном элементе в массиве при работе Split().

rami

Tigrik, вы ошиблись темой, вам нужно было писать в этой теме.


Функции Join и Split работают правильно.

mikekaganski

#2
@Tigrik, Я отделил Вашу тему.

Во-первых, полный ответ, конечно, Вам уже дан:
Цитата: rami от 12 июня 2020, 07:53Функции Join и Split работают правильно.

Во-вторых, спасибо @rami за ссылку! :)

Теперь для облегчения задачи @Tigrik, во-первых, в пустом документе Writer включите знаки форматирования (Ctrl+F10); далее два раза нажмите клавишу "A". Затем выполните "Поиск и замену" A на \n с включёнными регулярными выражениями, и посчитайте количество параграфов.

А во-вторых, обратите внимание на описание Join:

Цитироватьdelimiter (optional): A string character that is used to separate the substrings in the resulting string. The default delimiter is the space character

Это о том, почему у вас при объединении трёх пустых строк получается строка из двух пробелов. После прочтения вернитесь в тот же документ, где Вы заменяли A на \n и замените регулярное выражение $ на пробел.
С уважением,
Михаил Каганский

Tigrik

Спасибо Rami и Михаила за разъяснения.

"Не оправдания ради, а справедливости для..."
Я не говорил, что эти функции работают не правильно (в некоторых местах кода в моих комментариях есть некоторое непонимание - именно непонимание). Я попросил помочь в объяснении полученных результатов.
Этими функциями я пользовался всего пару раз и описании функций я читал, но там не было ничего про то, что символ "конца строки" "укладывается" в дополнительной ячейке полученного, после использования Split, массива. Скорее всего, там и не должно было быть таких "тонкостей", поэтому и спросил на форуме.
Резюмируя, можно сказать, что при ЛЮБОМ "расщеплении" ЛЮБОЙ строки будет дополнительный элемент массива (в конце этого массива), куда будет помещен символ "конца строки" первоначальной строки?

mikekaganski

Нет конечно. Вы на что-то не то смотрите.

Когда Вы используете Split, то каждое появление разделителя в строке делит эту строку на две части: "до" разделителя и "после". Каждое. Даже если после разделителя ничего нет, то такой разделитель в конце разделяет строку на две части: то что было до, и то, что после (пусто).

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

Tigrik

Цитата: mikekaganski от 12 июня 2020, 16:36
Нет конечно. Вы на что-то не то смотрите.

Когда Вы используете Split, то каждое появление разделителя в строке делит эту строку на две части: "до" разделителя и "после". Каждое. Даже если после разделителя ничего нет, то такой разделитель в конце разделяет строку на две части: то что было до, и то, что после (пусто).

Количество получившихся кусков батона всегда на 1 больше, чем количество разрезов.
Михаил, в первую очередь, я смотрю на код.

И Ваш пример с батоном понятен (хотя, по мне, лучше с колбасой - "папа может!"). :)

Практически, не "общаясь" со Split и Join, я себе не правильно представил алгоритм действий этих функций - не учел, что помимо видимых символов есть и другие, не видимые в обычном тексте.
Мне изначально и думалось, что сколько разделителей в Split, столько должно быть и элементов созданного массива. Но получилось, что не правильно мне думалось - иногда, невидимое становится видимым (символы "начало строки" и "конец строки").
Для себя я сделал простенький код, который помог мне увидеть "невидимое" - теперь надо как-то привыкать с этим жить. :)

  Dim aSim(), aText(), strTemp, i&, j&, s$
aSim() = Array("A", "B", "C")
strTemp = "ABCABC"
For i = 0 To 2
s = ""
aText() = Split(strTemp, aSim(i))
For j = LBound(aText()) To UBound(aText())
s = s +  j & "-й элемент массива: " & aText(j) & chr(10)
Next
Msgbox  s
Next


А мне все-то надо было "распихать" текст в массив по символу "новая строка"(chr(10)) и по пробелам!
По ходу дела, вроде бы, уже научился этому.

rami

Цитата: Tigrik от 12 июня 2020, 20:41Но получилось, что не правильно мне думалось - иногда, невидимое становится видимым (символы "начало строки" и "конец строки").
Для себя я сделал простенький код, который помог мне увидеть "невидимое" - теперь надо как-то привыкать с этим жить.
В строке "ABCABC" нет никаких символов "начало строки" и "конец строки" есть только шесть буквенных символов которые вы видите, ничего невидимого в ней нет.

Tigrik

Цитата: rami от 12 июня 2020, 21:32
Цитата: Tigrik от 12 июня 2020, 20:41Но получилось, что не правильно мне думалось - иногда, невидимое становится видимым (символы "начало строки" и "конец строки").
Для себя я сделал простенький код, который помог мне увидеть "невидимое" - теперь надо как-то привыкать с этим жить.
В строке "ABCABC" нет никаких символов "начало строки" и "конец строки" есть только шесть буквенных символов которые вы видите, ничего невидимого в ней нет.
А что тогда в первом элементе в первом цикле и в последнем элементе последнего цикла?
Пустая строка?

rami

Да, это пустая строка. Добавил пояснения в ваш код:
Sub Main
Dim aSim(), aText(), strTemp, i&, j&, s$
aSim() = Array("A", "B", "C")
strTemp = "ABCABC"
For i = 0 To 2
s = ""
aText() = Split(strTemp, aSim(i))
For j = LBound(aText()) To UBound(aText())
If len(aText(j)) = 0 Then        'проверяем длину строки
s = s +  j & "-й элемент массива: " & aText(j) & " это пустая строка " & chr(10)     'если длина равна 0
Else
s = s +  j & "-й элемент массива: " & aText(j) & chr(10)        'если есть символы в строке
End If
Next
Msgbox  s
Next
End Sub

Tigrik

Цитата: rami от 12 июня 2020, 22:08
Да, это пустая строка. Добавил пояснения в ваш код:
Спасибо большое.
Буду разбираться.