Что нового

[Массивы] Можно ли через _ArrayUnique удалить повторяющиеся значения в двухмерном массиве?

vaf

Новичок
Сообщения
190
Репутация
2
Добрый день уважаемые форумчане, столкнулся с задачей. Удалить повторяющиеся значение в файле с разделителями.
К примеру, есть файл со следующим содержанием

1;1;1;9839849879889959961002100710141020102610311042104710481055106210671075
1;1;2;983984987988995996100210071014102010261031104210471048105510621067
1;1;3;9839849879889959961002100710141020102610311042104710481055106210671075
1;1;8;
1;1;4;9839849879889959961002100710141020102610311042104710481055106210671075
1;1;5;983984987988995996100210071014102010261031104210471048105510621067
1;1;6;9839849879889959961002100710141020102610311042104710481055106210671075
1;1;7;9839849879889959961002100710141020102610311042104710481055106210671075
1;1;15;

Нужно удалить все одинаковые последние значения, чтобы в итоге получилось следующее
1;1;1;9839849879889959961002100710141020102610311042104710481055106210671075
1;1;5;983984987988995996100210071014102010261031104210471048105510621067
1;1;8;

Пробовал загрузить файл в массив, и через _ArrayUnique оставить только уникальные значения, но он удаляет все остальные стоблцы, т.е. в итоге получается вот так:

9839849879889959961002100710141020102610311042104710481055106210671075
983984987988995996100210071014102010261031104210471048105510621067
Подскажите, есть ли способ, быстро удалить повторяющиеся значения в данном файле ?
 

DarWiM

Продвинутый
Сообщения
527
Репутация
90
vaf
Не совсем понятно каким образом из оригинала получается результат. Что именно в строке/столбце должно быть уникально?
 
Автор
V

vaf

Новичок
Сообщения
190
Репутация
2
DarWiM сказал(а):
vaf
Не совсем понятно каким образом из оригинала получается результат. Что именно в строке/столбце должно быть уникально?
Уникальными должны быть только последние столбцы.
 

ildar

Осваивающий
Сообщения
252
Репутация
30
Судя по полученным результатам, обрабатывается только все после последней ";" и полученный результат верный. Если еще учитывать символы до ";", то они все уникальны.
И по каким параметром должно остаться?
Код:
1;1;8;
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
Re: через _ArrayUnique удалить повторяющиеся значения в двумерном массиве?

Хороший вопрос!
Редко на форуме задают такие качественные вопросы...

Итак, ТС загнал свой файл в двумерный массив и хочет удалить лишние строки, применив _ArrayUnique к второму столбцу.
Проблема заключается в том что _ArrayUnique выдёргивает их 2D массива только указанный столбик, формирует из него одомерный массив и получает результат только из данных этого одномерного массива.
А ТС хочет чтобы в результат попали значения всех столбиков, а второй столбик использовался бы как ключевое поле для определения уникальности.
Вобщем-то не сложная задача. Нужно взять результат _ArrayUnique, определить в начальном двумерном массиве индексы строк, полученных на выходе _ArrayUnique (например, через _ArrayIndex) и потом взять из двумерного массива эти строки.
Но красивым решением было бы на базе _ArrayUnique написать какую-нибудь функцию_ArrayUniqueEx, которая для двумерного массива сразу формирует словарь с запоминанием значений других столбцов.
Ну, тут я, к сожалению, помочь не могу - не разбирался со словарями, не знаю что они могут, чего не могут.
:(

Наглядно, на пальцах
Код:
#include <Array.au3>

$text = FileRead("test01.txt")
$pattern = "(.*;)(\d*)"

$aRes = StringRegExp($text, $pattern, 3)
If @error Then
	MsgBox(0, "ошибка", "файл не удалось разобрать")
	Exit
EndIf
_ArrayDisplay($aRes)

$iMax = UBound($aRes) / 2
Dim $a2D[$iMax][2]
For $i=0 To $iMax-1
	$a2D[$i][0] = $aRes[$i*2]
	$a2D[$i][1] = $aRes[$i*2+1]
Next
_ArrayDisplay($a2D)

$aArrayUnique = _ArrayUnique($a2D,1)
_ArrayDisplay($aArrayUnique)
 

madmasles

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

Opt('MustDeclareVars', 1)

Global $aArray
_FileReadToArray(@ScriptDir & '\1.txt', $aArray, $FRTA_NOCOUNT, ';');AutoIt v3.3.12.0+
_ArrayDisplay($aArray, 'Not Unique')
_Array2DUnique($aArray, 0, UBound($aArray, 2) - 1)
_ArrayDisplay($aArray, '_Array2DUnique: ' & @extended)

#cs
	Удаляет в 2-мерном массиве все повтроряющиеся строки в зависимости от $i_ColumnUniq.
	$a_Array		- 2-мерный массив.
	$i_Start		- индекс строки, начиная с которой идет проверка (только 0 или 1) (-1 = 0, Default = 0). По умолчанию -1.
	$i_ColumnUniq	- -1(или Default) - удалит все повтроряющиеся строки (если дан $a_Array[n][q], то строка = $a_Array[i][0] & $a_Array[i][1] & ... & $a_Array[i][q - 1])
	;				   0 - UBound($aArray, 2) - 1 удалит все строки, в которых в указанной колонке есть повтроряющиеся строки. По умолчанию  -1.
	$i_Casesense	- 0 - не учитывать регистр, 1 - учитывать. По умолчанию 0.
	При успехе вернет  1, флаг @error = 0 и флаг @extended = кол-во удаленных (повторяющихся) строк.
	При неудаче вернет 0 и флаг @error = :
	;	1			- $a_Array не 2-мерный массив.
	;	2			- $i_Start - некорректное значение.
	;	3			- $i_ColumnUniq - некорректное значение.
	;	4			- Ошибка создания объекта Scripting.Dictionary.
#ce
Func _Array2DUnique(ByRef $a_Array, $i_Start = -1, $i_ColumnUniq = -1, $i_Casesense = 0)
	Local $o_Dict, $i_Row, $i_Column, $a_TempArray = $a_Array, $i_Count, $s_Key, $i_All

	If UBound($a_TempArray, 0) <> 2 Then Return SetError(1, 0, 0)
	$i_Row = UBound($a_TempArray, 1)
	$i_Start = Number($i_Start)
	Switch $i_Start
		Case 0, 1
		Case -1, Default
			$i_Start = 0
		Case Else
			Return SetError(2, 0, 0)
	EndSwitch
	If $i_Row - $i_Start < 1 Then Return SetError(2, 0, 0)
	$i_Count = $i_Start
	$i_Column = UBound($a_Array, 2)
	Switch $i_ColumnUniq
		Case 0 To $i_Column - 1
		Case -1, Default
			$i_All = 1
		Case Else
			Return SetError(3, 0, 0)
	EndSwitch
	$o_Dict = ObjCreate('Scripting.Dictionary')
	If @error Then Return SetError(4, 0, 0)
	$o_Dict.CompareMode = Number(Not $i_Casesense)
	For $i = $i_Start To $i_Row - 1
		$s_Key = ''
		If $i_All Then
			For $j = 0 To $i_Column - 1
				$s_Key &= $a_TempArray[$i][$j]
			Next
		Else
			$s_Key &= $a_TempArray[$i][$i_ColumnUniq]
		EndIf
		If $o_Dict.Exists($s_Key) Then ContinueLoop
		$o_Dict.Item($s_Key)
		For $j = 0 To $i_Column - 1
			$a_Array[$i_Count][$j] = $a_TempArray[$i][$j]
		Next
		$i_Count += 1
	Next
	If $i_Count <> $i_Row Then ReDim $a_Array[$i_Count][$i_Column]
	Return SetExtended($i_Row - $i_Count, 1)
EndFunc   ;==>_Array2DUnique
 
Автор
V

vaf

Новичок
Сообщения
190
Репутация
2
ildar сказал(а):
Судя по полученным результатам, обрабатывается только все после последней ";" и полученный результат верный. Если еще учитывать символы до ";", то они все уникальны.
И по каким параметром должно остаться?
Код:
1;1;8;
да, остаться должны только уникальные последние (которые длинные), первые 1;1;8; без разницы какие будут.
 
Верх