Usuwanie pojedynczych wartości

Usuwanie pojedynczych wartości
Sebastian G
  • Rejestracja:prawie 6 lat
  • Ostatnio:prawie 5 lat
  • Postów:7
0

Witam. Posiadam kilka plików w których są wypisane pary kryptowalut np: USDTBTC. Wygląda to tak:

Kopiuj
NULSBTC
NEOBTC
NULSETH
LINKBTC
IOTABTC
ETCBTC

Kopiuj
NULSBNB
BNBBTC
NULSBTC
NEOBTC
NULSETH
LINKBTC
IOTABTC
ETCBTC

Kopiuj
NULSBNB
BNBBTC
LINKBTC
IOTABTC
USDTBTC

Chodzi o to, że tylko raz występuje np.USDTBTC, więc chce to usunąć. Jeśli w tych zbiorach jest więcej niż 2 takie same wartości to zostawiam, jeśli jest tylko jedna na wszystkie zbiory to usuwam. Jak to zrobić? Pozdrawiam

szweszwe
Kod chcesz czy nie masz pomysłu w ogóle na implementację?
Sebastian G
Pomysł ew. jakaś funkcja która mi pomoże
AF
  • Rejestracja:prawie 7 lat
  • Ostatnio:4 dni
  • Postów:172
0

Przeleć przez zbiory i zlicz ile czego masz. Np:

Kopiuj
import collections
c = collections.Counter()
with open('your_file.txt', 'r') as f:
        c.update(f)

c będzie kontenerem (dictem) który zawiera informacje co ile razy występuje. Wyrzuć wszystko co występuje tylko raz i zostaw jako set(liczniki już nie potrzebne):

Kopiuj
c_filtered = {x for x in c if c[x] > 1}

Następnie możesz przeglądać swój zbiór raz jeszcze i akceptować tylko te, które są w c_filtered:

Kopiuj
for item in container:
    if item not in c_filtered:
        continue
    #do whatever 

Pisane z palca więc mogą być błędy w składni i logice ;)

edytowany 1x, ostatnio: AsterFV
DJ
  • Rejestracja:około 8 lat
  • Ostatnio:prawie 5 lat
  • Postów:35
0
Kopiuj
data_sets = [['NULSBNB', 'BNBBTC','NULSBTC', 'NEOBTC', 'NULSETH', 'LINKBTC', 'IOTABTC', 'ETCBTC'], ['NULSBTC','NEOBTC','NULSETH','LINKBTC','IOTABTC','ETCBTC'], 
                ['NULSBNB','BNBBTC','LINKBTC','IOTABTC','USDTBTC']]

def get_logest_set(data_sets):
    longes_set_idx = 0
    max_set = 0
    for idx, item in enumerate(data_sets):
        if len(item) > max_set:
            longes_set_idx = idx
            max_set = len(item)
    return longes_set_idx
    
def create_template(logest_set):
    tmp = {}
    for item in logest_set:
        if item not in tmp.keys():
            tmp[item] = 1
        else:
            tmp[item] += 1
    return tmp
    
logest_data_set = get_logest_set(data_sets)
template = create_template(data_sets[logest_data_set])
data_cp = data_sets[:]
data_cp.pop(logest_data_set)
to_delete = []
for item in data_cp:
    for i in item:
        if i in template.keys():
            template[i] += 1
        else:
            template[i] = 1
        
for k, v in template.items():
    if v < 2:
        to_delete.append(k)
        
for idx, item in enumerate(data_sets):
    for i, data in enumerate(item):
        if item in to_delete:
            data_sets[idx].pop(i)
            
print(data_sets)
            

Tu masz baaaardzo po kolei tak dla zrozumienia jak co sie dzieje :)

Guaz
  • Rejestracja:około 8 lat
  • Ostatnio:ponad 4 lata
  • Lokalizacja:Częstochowa
  • Postów:221
0

Zakładając że chcesz to przechowywać w pliku w formie tekstowej, nie istnieje w pojęciu pliku coś takiego jak usuwanie jego treści, tylko nadpisanie go nową wersją bez fragmentów które są nam zbędne. Zakładając że będziesz robił to częściej i jesteś na etapie który jeszcze nie zaburzy całej pracy programu, lepiej zapisać strukturę w formacie JSON, albo za pomocą pickle.
Gdybyś stworzył strukturę z Flagami bitowymi, każda flaga odpowiada innemu 'plikowi', możesz selektywnie sobie wybierać te które znajdują się w chociaż dwóch plikach, suma flag bitowych w takich warunkach będzie większa od dwóch i różna od czterech. Wczytanie struktury, będzie efektywniejsze od parsowania pliku, zliczania elementów i tworzenia struktury liczącej za każdym razem. Równie szybko możesz odfiltrować te które potrzebujesz.

Jeśli nie możesz tego już zmienić, i chcesz po prostu usuwać pojedyńcze rekordy ze zbioru plików, to @AsterFV podał dość dobry sposób z jednym wyjątkiem, załóżmy że z każdego pliku chcemy 'usunąć' pojedyńcze wystąpienie, musimy więc wiedzieć w których plikach są pozostałe rekordy.
Najprostsze rozwiązanie jakie ja widzę:

Kopiuj
def remove_unique_lines(filenames):
	files_container = {}
	for filename in filenames:
		with open(filename, "r") as f:
			files_container[filename] = f.read()

	for filename, text in files_container.items():
		with open(filename, "w") as f:
			for line in text:
				if count_from_iterable(files_container.values(), line) > 1:
					f.write(line)
        
def count_from_iterable(iter, search):
    counter = 0
    for elem in iter:
        counter += elem.count(search)
    return counter
    
if __name__ == "__main__":
	filenames = ("1.txt", "2.txt", "3.txt")
	remove_unique_lines(filenames)

Mogłem się gdzieś machnąć, ale mniej więcej podobnie do tego mogłoby to wyglądać :)
Da się to zrobić optymalniej:
-Nie przeszukiwać tekstu z którego bierzesz te linię.
Albo jeszcze lepiej:
-Zastosować counter jak kolega wyżej ale zapamiętując pliki które trzeba później przelecieć, a później tylko wyszukiwać ile razy w counterze znajduje się linia, wtedy ją zapisać lub nie zależnie od ilości wystąpień...


Linux Mint
Arduino / Python 3.5.2
edytowany 1x, ostatnio: Guaz
  • Rejestracja:około 6 lat
  • Ostatnio:ponad rok
0
Kopiuj
what=$(sort -- "$@" | uniq -d)
for file in "$@"; do
    mv -- "$file"{,.orig}
    grep -F -x -f <<<"$what" "$file.orig" >"$file"
done
edytowany 1x, ostatnio: Mózg

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.