Что нового

Как отсортировать массив по алфавиту

StarEdik

Новичок
Сообщения
365
Репутация
4
Привет всем.
Надо отсортировать полученный массив по алфавиту, чтоб русские и английские соответствующие заглавные буквы были отсортированы вместе.
All
Aleks
Aвтомобиль
Борис
Boris
Бабушкин
Fedor
Федор
farm
Семь
Sindy
Sophie
Обычное сортировка здесь не подходить
Код:
_ArraySort($a_Sp, 1)
_ArrayDisplay($a_Sp)
 

edyapd

Осваивающий
Сообщения
380
Репутация
30
Из того как это вижу я:
1. Создаёте отсортированый массив букв.
2. Берёте первое слово из несортированого массива и ищете индекс первой буквы в массиве букв.
3. Тоже самое со вторым словом.
4. Сравниваете индексы и меняете местами слова если первый индекс оказался больше второго.
5. Повторяете до полной сортировки массива слов.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
StarEdik,
Сделайте дополнительную колонку, поместите в нее первые буквы слов, заменив русские на нужные Вам (типа транслит), и отсортируйте по ней.
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
Всё это похоже на какую-то разводку...
Смотрю в Array.au3 функцию _ArraySort, которая вызывает __ArrayQuickSort1D, а та в свою очередь использует StringCompare
Офигеваю :shok:
Проверяю
Код:
#include <Array.au3>
Dim $aData[12] = ['All','Aleks','Aвтомобиль','Борис','Boris','Бабушкин','Fedor','Федор','farm','Семь','Sindy','Sophie']
_ArrayDisplay($aData)
_ArraySort($aData)
_ArrayDisplay($aData)


Получаю
Код:
Aleks
All
Aвтомобиль
Boris
farm
Fedor
Sindy
Sophie
Бабушкин
Борис
Семь
Федор

А что не так?!
А-а-а, ещё и слово Автомобиль написано с латинской 'A'.
Офигеть! Это ж вроде раздел не прочего юмора.
И до 1-го апреля ещё прилично...
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
StarEdik [?]
Надо отсортировать полученный массив по алфавиту, чтоб русские и английские соответствующие заглавные буквы были отсортированы вместе.
Код:
All		- en - Ok
Aleks		- en - Ok
Aвтомобиль	- ru - Ok
Борис		- ru - Где логика почему не Boris?
Boris		- en - Где логика почему не Бабушкин?
Бабушкин	- ru - Где логика Борис?
Fedor		- и т.д.
Федор
farm
Семь
Sindy
Sophie
 
Автор
StarEdik

StarEdik

Новичок
Сообщения
365
Репутация
4
Всем спасибо. Наверно я не так объяснил. Дело в том, что из текста нужно найти все имена. Но не все имена в тексте написаны на русском. Скрипт находить все имена и отображает сортируя по алфавиту в таком порядке.
Код:
Aleks
Allа
Boris
farm
Fedor
Sindy
Sophie
Aвтомобиль
Бабушкин
Борис
Семь
Федор
Из сортировки видно, что сперва идут имена на английском а потом на русском. А нужно сортировать как просил друг мой. Так, что не ищите здесь развода и логики. Борисы должны быть вместе как и Fedorы. Думал нужно все заглавные русские буквы в именах как то заменить на соответствующие заглавные буквы английского алфавита. Но не знаю как.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
StarEdik [?]
Дело в том, что из текста нужно найти все имена.
Вопрос, как вы собираетесь идентифицировать имена?
Например, что здесь является именем Boris, Автомобиль и Нисан?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
StarEdik,
Можно примерно так сделать.
Код:
#include <Array.au3>

Opt('MustDeclareVars', 1)

Global $aRU_EN = StringSplit('All|Aleks|Boris|Fedor|farm|Sindy|Sophie|Автомобиль|Борис|Бабушкин|Федор|Семь', '|')

_ArrayDisplay($aRU_EN, 'До')
_Sort_1D_Array_Ru_En($aRU_EN, 0, 1)
_ArrayDisplay($aRU_EN, 'После')

Func _Sort_1D_Array_Ru_En(ByRef $a_Array, $i_Descending = 0, $i_Start = 0)
	Local $i_Ub
	If UBound($a_Array, 0) <> 1 Then Return 0
	$i_Ub = UBound($a_Array)
	Local $a_Tmp[$i_Ub][2]
	For $i = 0 To $i_Ub - 1
		$a_Tmp[$i][0] = $a_Array[$i]
		$a_Tmp[$i][1] = StringLeft($a_Array[$i], 1)
		__Replace_Letter_Ru_To_En($a_Tmp[$i][1])
	Next
	_ArraySort($a_Tmp, $i_Descending, $i_Start, 0, 1)
	For $i = 0 To $i_Ub - 1
		$a_Array[$i] = $a_Tmp[$i][0]
	Next
	Return 1
EndFunc   ;==>_Sort_1D_Array_Ru_En

Func __Replace_Letter_Ru_To_En(ByRef $s_Letter)
	Local Const $s_Ru = 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ', $s_En = 'ABVGDEEGZIIKLMNOPRSTUFHCCSSZIZEYY'
	Local $i_Ind = StringInStr($s_Ru, $s_Letter)
	If $i_Ind Then $s_Letter = StringMid($s_En, $i_Ind, 1)
EndFunc   ;==>__Replace_Letter_Ru_To_En
Или так.
Код:
#include <Array.au3>

Opt('MustDeclareVars', 1)

Global $aRU_EN = StringSplit('All|Aleks|Boris|Fedor|farm|Sindy|Sophie|Автомобиль|Борис|Бабушкин|Федор|Семь', '|')

_ArrayDisplay($aRU_EN, 'До')
_Sort_1D_Array_Ru_En($aRU_EN, 0, 1)
_ArrayDisplay($aRU_EN, 'После')

Func _Sort_1D_Array_Ru_En(ByRef $a_Array, $i_Descending = 0, $i_Start = 0)
	Local $i_Ub
	If UBound($a_Array, 0) <> 1 Then Return 0
	$i_Ub = UBound($a_Array)
	Local $a_Tmp[$i_Ub][2]
	For $i = 0 To $i_Ub - 1
		$a_Tmp[$i][0] = $a_Array[$i]
		$a_Tmp[$i][1] = StringLeft($a_Array[$i], 1)
		__Replace_Letter_Ru_To_En($a_Tmp[$i][1])
	Next
	_ArraySort($a_Tmp, $i_Descending, $i_Start, 0, 1)
	For $i = 0 To $i_Ub - 1
		$a_Array[$i] = $a_Tmp[$i][0]
	Next
	Return 1
EndFunc   ;==>_Sort_1D_Array_Ru_En

Func __Replace_Letter_Ru_To_En(ByRef $s_Letter)
	Local Const $s_Ru = 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ', $a_En[34] = [33, 'A', 'B', 'V', 'G', 'D', 'E', 'YO', 'ZH', 'Z', 'I', 'Y', 'K', 'L', 'M', _
			'N', 'O', 'P', 'R', 'S', 'T', 'U', 'F', 'KH', 'TC', 'CH', 'SH', 'SHC', '''', 'Y', '''', 'E''', 'YU', 'YA']
	Local $i_Ind = StringInStr($s_Ru, $s_Letter)
	If $i_Ind Then $s_Letter = $a_En[$i_Ind]
EndFunc   ;==>__Replace_Letter_Ru_To_En
Буквы-замены брал здесь. Можно добавить опцию сортировки не только по одной первой букве, а, например, по одной - трем.
 
Автор
StarEdik

StarEdik

Новичок
Сообщения
365
Репутация
4
Дорогой и много уважаемый мною Garrett!!!

Вопрос, как вы собираетесь идентифицировать имена?
Не знаю, казалось вы знаете.
Думал сделать как посоветовал любезный madmasles. Но не смог. И по этому я предложил своему другу сортировать не по именам а по буквам. То есть, скрипт уже сортирует, после этого нужно заменить первые буквы русских имен на соответствующие заглавные буквы английского алфавита. Допустим Б на В_Б. Тогда получим такой список
Код:
Aleks
Allа
A_Aвтомобиль
Boris
B_Бабушкин
B_Борис
farm
Fedor
F_Федор
Sindy
Sophie
S_Семь
А потом убрать первую букву с черточкой. И получим
Код:
Aleks
Allа
Aвтомобиль
Boris
Бабушкин
Борис
farm
Fedor
Федор
Sindy
Sophie
Семь

Но любезный madmasles опередил меня.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
madmasles [?]
Можно добавить опцию сортировки не только по одной первой букве, а, например, по одной - трем.
Например, так.
Код:
#include <Array.au3>

Opt('MustDeclareVars', 1)

Global $aRU_EN = StringSplit('All|Aleks|Boris|Fedor|farm|Sindy|Sophie|Zoom|Yashied|Stop|Автомобиль|Борис|Бабушкин|Федор|Семь|яблоко|зверь|шип|щит|чум|цепь', '|')

_ArrayDisplay($aRU_EN, 'До')
_Sort_1D_Array_Ru_En($aRU_EN, 0, 1, 3)
_ArrayDisplay($aRU_EN, 'После')

Func _Sort_1D_Array_Ru_En(ByRef $a_Array, $i_Descending = 0, $i_Start = 0, $i_CountFirstLetters = 1)
	Local $i_Ub, $s_Tmp
	If UBound($a_Array, 0) <> 1 Then Return 0
	Switch $i_CountFirstLetters
		Case 1 To 3
		Case Else
			$i_CountFirstLetters = 1
	EndSwitch
	$i_Ub = UBound($a_Array)
	Local $a_Tmp[$i_Ub][2]
	For $i = 0 To $i_Ub - 1
		$a_Tmp[$i][0] = $a_Array[$i]
		For $j = 1 To $i_CountFirstLetters
			$s_Tmp = StringMid($a_Array[$i], $j, 1)
			If Not $s_Tmp Then ExitLoop
			__Replace_Letter_Ru_To_En($s_Tmp)
			$a_Tmp[$i][1] &= $s_Tmp
		Next
	Next
	_ArraySort($a_Tmp, $i_Descending, $i_Start, 0, 1)
	For $i = 0 To $i_Ub - 1
		$a_Array[$i] = $a_Tmp[$i][0]
	Next
	Return 1
EndFunc   ;==>_Sort_1D_Array_Ru_En

Func __Replace_Letter_Ru_To_En(ByRef $s_Letter)
	Local Const $s_Ru = 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ', $a_En[34] = [33, 'A', 'B', 'V', 'G', 'D', 'E', 'YO', 'ZH', 'Z', 'I', 'Y', 'K', 'L', 'M', _
			'N', 'O', 'P', 'R', 'S', 'T', 'U', 'F', 'KH', 'TC', 'CH', 'SH', 'SHC', '''', 'Y', '''', 'E''', 'YU', 'YA']
	Local $i_Ind = StringInStr($s_Ru, $s_Letter)
	If $i_Ind Then $s_Letter = $a_En[$i_Ind]
EndFunc   ;==>__Replace_Letter_Ru_To_En
Прикручивать сортировку 2-ух мерного массива уже лень. :smile:


Добавлено:
Сообщение автоматически объединено:

Можно поменять англ. замены, выбрав нужные Вам здесь: правила транслита
 
Автор
StarEdik

StarEdik

Новичок
Сообщения
365
Репутация
4
Дорогой madmasles, как всегда вы на высоте. Респект вам и спасибо за примеры. :ok: премного благодарен. Отдельно спасибо вам Garrett. Как хорошо, что вы есть. :beer: :IL_AutoIt_1:
 
Верх