Что нового

[Данные, строки] Удаление похожих строк с минимальными значениями

forc1k

Новичок
Сообщения
42
Репутация
1
Здравствуйте. Есть файл со строками вида:
Код:
46V178E2F;Значение D10;12;[БД >> Первая база];+;;;;46V178E2F-12:null:null:1000:500:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;5244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-
...
...
...
V6K8Q7P3A7;Значение D10;5;[БД >> Первая база];+;;;;V6K8Q7P3A7-5:null:null:1200:590:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;5244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-

Вид строк всегда один, отличаются лишь некоторые данные. Пытаюсь сделать удаление дубликатов строк(строк может быть несколько тысяч). Значения по которым надо вести поиск из примеров - Значение D10, соответственно в обеих строках они совпадают, нужно оставить строку(повторяющихся строк может быть более двух и находиться они могут в различных местах) с наименьшими значениями - null:null:1000:500:100, соответственно среди этих двух строк, наименьшие значения у первой строки "1000" и "500", а значит оставить нужно именно ее, а строку со значениями "1200" и "590" удалить полностью. Может кто чего сможет подсказать? Нужна любая помощь.
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
forc1k
другими словами из кучи строк нужно оставить строки в которых есть подстрока Значение D10 и подстрока null:null:1000:500:100 ?
Код:
StringInStr

не подходит? минимальные значения null всегда одинаковы?
 
Автор
F

forc1k

Новичок
Сообщения
42
Репутация
1
joiner сказал(а):
forc1k
другими словами из кучи строк нужно оставить строки в которых есть подстрока Значение D10 и подстрока null:null:1000:500:100 ?
Код:
StringInStr

не подходит? минимальные значения null всегда одинаковы?
поправка, подстрока null:null:1000:500:100 значение имеет только "1000" и "500", они в каждой строке разные. Значения null:null: и :100 всегда статичны.
Нет, видимо я неправильно выразился. Попробую дополнить. Итак, есть, скажем, 1000 строк. 500 из них уникальны(т.е. вместо Значение D10 там может быть любой текст) и каждая из них имеет повторы(необязательно, просто для примера), вот от этих повторов и надо избавиться. Для наглядности часть строк:
Код:
46V178E2F;Значение D10;12;[БД >> Первая база];+;;;;46V178E2F-12:null:null:1000:500:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;5244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-
44QQQ8E2F;Data 10;4;[БД >> Первая база];+;;;;44QQQ8E2F-4:null:null:300:120:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;6244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-
V6K8Q7P3A7;Значение D10;5;[БД >> Первая база];+;;;;V6K8Q7P3A7-5:null:null:1200:590:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;5244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-
13QDKSDL2F;Data 10;1;[БД >> Первая база];+;;;;13QDKSDL2F-1:null:null:500:240:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;6244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-
Т.е. вместо Значение D10 и Data 10 могут быть абсолютно любые данные, если приводить в пример, можно сравнить с товаром, "Значение D10" - товар1, "Data 10" - товар2, а значения 1000:500, 300:120, 1200:590, 500:240 - цена, т.е. нужно оставить товар с минимальным значением цены. Надеюсь, сейчас понятно объяснил то, что я хочу сделать.
В итоге должен происходить построчный скан на предмет дубликатов по значению "Значение D10"(или любое другое, между этими разделителями цифрыбуквы;нужное значение;[ если дубликатов не найдено - хорошо, если найдены, оставить одну строку с минимальными значениями после null:null: и до :100, т.е. в примерах это 1000:500, 300:120, 1200:590, 500:240
Конкретно в этих строках необходимо оставить следующие строки, ибо они имеют минимальные нужные значения:
Код:
46V178E2F;Значение D10;12;[БД >> Первая база];+;;;;46V178E2F-12:null:null:1000:500:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;5244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-
44QQQ8E2F;Data 10;4;[БД >> Первая база];+;;;;44QQQ8E2F-4:null:null:300:120:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;6244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-
Код:
StringInStr
- не подойдет или же я не понимаю, как его можно применить. Очень хотелось бы пример, для моей ситуации.
 

edyapd

Осваивающий
Сообщения
380
Репутация
30
Ещё одно уточнение.
Из этих двух строк какую надо оставить?
Код:
46V178E2F;Значение D10;12;[БД >> Первая база];+;;;;46V178E2F-12:null:null:1000:750:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;5244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-

V6K8Q7P3A7;Значение D10;5;[БД >> Первая база];+;;;;V6K8Q7P3A7-5:null:null:1200:590:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;5244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-
То есть если один параметр больше, а другой меньше. Или такого не может быть?
 
Автор
F

forc1k

Новичок
Сообщения
42
Репутация
1
edyapd сказал(а):
Ещё одно уточнение.
Из этих двух строк какую надо оставить?
Код:
46V178E2F;Значение D10;12;[БД >> Первая база];+;;;;46V178E2F-12:null:null:1000:750:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;5244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-

V6K8Q7P3A7;Значение D10;5;[БД >> Первая база];+;;;;V6K8Q7P3A7-5:null:null:1200:590:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;5244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-
То есть если один параметр больше, а другой меньше. Или такого не может быть?
Такого быть не может, там есть определенная прогрессия, зависит от величины второго параметра(на примере 750 или 590, просто там где 750, первый параметр будет больше, скажем 1500 и в итоге надо оставить вторую строку), первый параметр будет всегда больше, если больше второй параметр.
P.S. Кстати говоря, Вы открыли для меня очевидное, что ПЕРВЫЙ параметр вовсе не нужен, для сравнения. Нужен только ВТОРОЙ, на примерах из Вашего сообщения это 750 и 590.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Автор
F

forc1k

Новичок
Сообщения
42
Репутация
1
madmasles сказал(а):
forc1k,
[info border=#0000ff float=left]С такой постановкой вопроса Вам надо в Стол заказов.
Переоформите тему в соответствии с Правилами обязательного оформления тем в разделе "Стол заказов" и я ее туда перенесу.[/info]


В данной теме я попросил помощи, любой помощи, хотя бы направление реализации и/или пример, я не просил "делать все за меня"(если кто-то сможет - здорово, нет так нет, буду ковырять сам). Просто у меня нет идей, как это можно сделать и любая помощь будет мне полезна. Так что, пожалуй, с переносом темы необходимо повременить, может кто сможет дать дельные советы по реализации.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
forc1k [?]
хотя бы направление реализации и/или пример

Код:
$sData = '46V178E2F;Значение D10;12;[БД >> Первая база];+;;;;46V178E2F-12:null:null:1000:750:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;5244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-'
$aData = StringSplit($sData, ';:', 2)
MsgBox(0, '', $aData[11] & @CRLF & $aData[12])

$sData = 'V6K8Q7P3A7;Значение D10;5;[БД >> Первая база];+;;;;V6K8Q7P3A7-5:null:null:1200:590:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;5244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-'
$aData = StringSplit($sData, ';:', 2)
MsgBox(0, '', $aData[11] & @CRLF & $aData[12])
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
как я , все-таки, понял (надеюсь), нужно не просто число сравнить, но и должно остаться по одному упоминанию значения
то есть в списке должно остаться, к примеру, только одно имя Значение D10 с наименьшим числом. по этому же примеру обработать и остальные имена в списке.
получается, что нужно выбрать сначала все строки с одним именем и сравнить числа...
автор, я так рассуждаю? :smile:
 
Автор
F

forc1k

Новичок
Сообщения
42
Репутация
1
Garrett сказал(а):
forc1k [?]
хотя бы направление реализации и/или пример

Код:
$sData = '46V178E2F;Значение D10;12;[БД >> Первая база];+;;;;46V178E2F-12:null:null:1000:750:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;5244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-'
$aData = StringSplit($sData, ';:', 2)
MsgBox(0, '', $aData[11] & @CRLF & $aData[12])

$sData = 'V6K8Q7P3A7;Значение D10;5;[БД >> Первая база];+;;;;V6K8Q7P3A7-5:null:null:1200:590:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;5244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-'
$aData = StringSplit($sData, ';:', 2)
MsgBox(0, '', $aData[11] & @CRLF & $aData[12])
Благодарю, я так понимаю алгоритм такой: попробую считать файл построчно, затем брать каждую отдельную строку начиная с первой, регуляркой брать "Значение D10" между разделителями искать все строки с этим значением, помещать их в переменные, потом стрингсплит и оставлять строку с наименьшим значением. Вопрос в связи с этим, как мне при таком раскладе, лучше всего запомнить из каких строк в файле взяты данные, чтобы потом удалить дубликаты?

joiner сказал(а):
как я , все-таки, понял (надеюсь), нужно не просто число сравнить, но и должно остаться по одному упоминанию значения
то есть в списке должно остаться, к примеру, только одно имя Значение D10 с наименьшим числом. по этому же примеру обработать и остальные имена в списке.
получается, что нужно выбрать сначала все строки с одним именем и сравнить числа...
автор, я так рассуждаю? :smile:
Все абсолютно верно, то что мне и нужно :smile:
p.s. Извиняюсь за "кривую" постановку задачи, я еще не спал :smile:
 

edyapd

Осваивающий
Сообщения
380
Репутация
30
Если общее направление то я вижу примерно так:
1. Создаёте массив строк.
2. Берёте первую строку из этого массива и с помощью StringSplit достаёте из неё значение для поиска (Значение D10, Data 10)
3. Ищите это значение во всех остальных строках.
3.1 Если найдено, то делаете для этой строки тоже StringSplit и сравниваете параметры (1000, 1200). Строку с наименьшим параметром записываете в новый массив.
3.2 Если не найдено строки с подобным значением (Значение D10, Data 10), то просто записываете её в новый массив.
4. Сохраняете полученый массив.
 
Автор
F

forc1k

Новичок
Сообщения
42
Репутация
1
edyapd сказал(а):
Если общее направление то я вижу примерно так:
1. Создаёте массив строк.
2. Берёте первую строку из этого массива и с помощью StringSplit достаёте из неё значение для поиска (Значение D10, Data 10)
3. Ищите это значение во всех остальных строках.
3.1 Если найдено, то делаете для этой строки тоже StringSplit и сравниваете параметры (1000, 1200). Строку с наименьшим параметром записываете в новый массив.
3.2 Если не найдено строки с подобным значением (Значение D10, Data 10), то просто записываете её в новый массив.
4. Сохраняете полученый массив.
Значения для поиска(Значение D10, Data 10 и так далее) - неизвестны, точнее их тысячи различных. Тут же нужно регулярное выражение, для выборки нужного значения между разделителями и тут у меня возникает вопрос насчет дальнейшего алгоритма... :stars:
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
forc1k,
Мне закрыть тему?
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
попробуй так. не изящно. но вроде..
Код:
#include <String.au3>
#include <array.au3>
$frta = FileReadToArray('1.txt');наш файл со строками
Local $getn, $name
For $i = 0 To UBound($frta) - 1
	$data = StringSplit($frta[$i], ';')
	If @error Then ContinueLoop
	$name = $data[2]
	$num = StringSplit($data[9], ':')
	$getn = Number($num[5])
	For $n = 0 To UBound($frta) - 1
		If StringInStr($frta[$n], $name) Then
			$bnum = StringSplit($frta[$n], ':')
			If $getn < Number($bnum[5]) Then
				$frta[$n] = ''
			EndIf
		EndIf
	Next
Next
_ArrayDisplay($frta)
 
Автор
F

forc1k

Новичок
Сообщения
42
Репутация
1
joiner сказал(а):
попробуй так. не изящно. но вроде..
Код:
#include <String.au3>
#include <array.au3>
$frta = FileReadToArray('1.txt');наш файл со строками
Local $getn, $name
For $i = 0 To UBound($frta) - 1
	$data = StringSplit($frta[$i], ';')
	If @error Then ContinueLoop
	$name = $data[2]
	$num = StringSplit($data[9], ':')
	$getn = Number($num[5])
	For $n = 0 To UBound($frta) - 1
		If StringInStr($frta[$n], $name) Then
			$bnum = StringSplit($frta[$n], ':')
			If $getn < Number($bnum[5]) Then
				$frta[$n] = ''
			EndIf
		EndIf
	Next
Next
_ArrayDisplay($frta)
Поменял строки местами:
Код:
V6K8Q7P3A7;Значение D10;5;[БД >> Первая база];+;;;;V6K8Q7P3A7-5:null:null:1200:590:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;5244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-
13QDKSDL2F;Data 10;1;[БД >> Первая база];+;;;;13QDKSDL2F-1:null:null:500:240:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;6244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-
46V178E2F;Значение D10;12;[БД >> Первая база];+;;;;46V178E2F-12:null:null:1000:500:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;5244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-
44QQQ8E2F;Data 10;4;[БД >> Первая база];+;;;;44QQQ8E2F-4:null:null:300:120:100;кк;0,00;0,00;0,00;;;;## - ##;## - ##;## - ##;##;6244.jpg;;;"Значение для записи";QQQ;-;;;;;;;-
И теперь не работает :scratch:
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
это как?
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
forc1k [?]
И теперь не работает
think.gif

все работает. возвращает две строки
null:null:1000:500:100
null:null:300:120:100
нужно было вернуть наименьшие значения или опять планы поменялись ? :smile:
 
Автор
F

forc1k

Новичок
Сообщения
42
Репутация
1
Garrett сказал(а):
forc1k [?]
И теперь не работает
Вам направление и пример дали!
Или...
Вам madmasles написал в стол заказов.
Мне кроме joiner'a никто ничего правильно не дал, ни алгоритма, ни примера. Его пример почему-то при тех же данных с измененным порядком не заработал, поинтересовался у него в чем может быть дело. Он пояснил где я не прав, за что ему огромное спасибо. Joiner - молодец. Тему можно закрывать.
joiner сказал(а):
forc1k [?]
И теперь не работает
think.gif

все работает. возвращает две строки
null:null:1000:500:100
null:null:300:120:100
нужно было вернуть наименьшие значения или опять планы поменялись ? :smile:
Огромное спасибо за помощь ! ;)
 
Верх