Usuwanie powtarzających się słów w skrypcie

0

Witam,
Zastanawiam się jak zabrać się za tego zadania w możliwie najprostszy sposób. Myślałem o implementacji tego w języku Ruby, ponieważ jest raczej równie funkcjonalny jak Perl (nie ubliżając drugiemu, potężnemu językowi) o wiele lepiej mi się w nim pisze dzięki specyficznym podejściu do iteratorów, wszechobecnym programowaniu obiektowym itp. Nie mam zamiaru wywoływać flamów czy podawać wyższośc języka X nad Y, po prostu zależy mi na ogólnym rozwiązaniu problemu bo nigdy czegoś podobnego nie robiłem i zależy mi na jakimś punkcie zaczepienia. Mam nadzieję drodzy forumowicze, że będziecie wyrozumiali - chcę się nauczyć praktycznego skrypcenia, a do tego trzeba pisać. I uczyć się od lepszych. :)

  1. Czy problem tego typu można rozwiązać za pomocą pojedynczego wyrażenia regularnego? Potrafię pisać proste wyrażenia regularne np. do walidacji daty czy też maila, ale wiem że potrafią znacznie więcej i ciekaw jestem czy tego typu problem może zostać podobnie rozwiązany.

  2. Na początek wczytuje plik, w języku Ruby wystarczy jedna linia (bo Ruby jest prosty):

data = File.open(filename).readlines

W rezultacie otrzymuje tablicę, każda linia jest w oddzielnej komórce.
2. Na każej linii wykonuję procedurę, iterator collect powoduje, że dana linia zostanie w razie potrzeby zmodyfikowana.

data.collect! { |line| moja_metoda(line) }

Cały problem w tym, że nie wiem jak najlepiej napisać tą metodę. Na pewno można zrobić to na wiele sposobów. Ale będzie fajnie jak zostanie wskazana mi ścieżka typowa dla typowych skrypciarzy piszących w popularnych językach perl / ruby / python / bash.

Pozdrawiam,

0

No dobrze, gdzie pytanie? Potrzebujesz funkcji (tak, funkcji, nie procedury) jednoargumentowej, tyle wiemy. Co ta funkcja ma robić, jakie zadanie realizować?

Nie żebym chciał flame'a robić, ale w każdym sensownym języku wczytanie i proste przetworzenie to będzie jedna linia. Python:

jużPrzedtworzoneDane = [ funkcja(linia) for linia in open('plik') ]
0

"Pytanie" zapewne jest w tytule wątku.
W Pythonie najszybciej można usunąć duplikaty przy użyciu słownika, ale przy dużych plikach może to być nieoptymalne. Jeśli już wczytujesz wszystko do tablicy (zamiast użyć generatora), to możesz też ją posortować (nawet in-place) i odrzucać przy zapisie (czy wypisie) elementy, dla których n == n - 1. Innym podejściem byłoby przelecenie całej tablicy i kopiowanie do innej elementów, które się tam jeszcze nie znajdują (szybsze, ale więcej pamięci zżera). Pewnie jeszcze się znajdzie jakiś sposób.

0

@Kumashiro, pytania chyba jednak brak. W tablicy masz wiersze pliku, tytuł wątku mówi o usuwaniu duplikatów słów ze skryptu. Wiersz może zawierać wiele słów (chyba). To trzeba sprecyzować. Czego oczekuje autor gdy skrypt wygląda np tak:
//O cholera, o co chodzi
o nic ważnego nie chodzi
Ma się pojawić nowy skrypt z zawartością
//O cholera, co chodzi
nic ważnego nie//?

0

Punkt zaczepienia (bo nie do końca działa tak jak chcesz):

data = File.open(filename).read.scan(/\w+/).uniq
 
0
bo napisał(a)

@Kumashiro, pytania chyba jednak brak. W tablicy masz wiersze pliku, tytuł wątku mówi o usuwaniu duplikatów słów ze skryptu.

Skrypty zazwyczaj zapisuje się w plikach, zatem rozdział tutaj nie ma sensu. Problem dotyczy usuwania duplikatów słów z pliku. Zakładam, że format danych nie ma znaczenia, bo jeśli chodzi o usuwanie duplikatów ze źródła w nieokreślonym języku programowania, to autor wątku raczej potrzebuje jakichś środków antyfilozoficznych.

bo napisał(a)

Wiersz może zawierać wiele słów (chyba). To trzeba sprecyzować. Czego oczekuje autor gdy skrypt wygląda np tak:
//O cholera, o co chodzi
o nic ważnego nie chodzi
Ma się pojawić nowy skrypt z zawartością
//O cholera, co chodzi
nic ważnego nie//?

Do sprecyzowania to jest wiele rzeczy. Np. czy unikalne słowa w wyniku mają zachowywać oryginalny szyk, czy można je przemieszać. Czy chodzi o usuwanie duplikatów w obrębie całego pliku, czy tylko sąsiadujące ze sobą. Itd. itp. Autor tego nie określił, zatem najwyraźniej zadowalają go rozwiązania ogólne, a nie konkretna implementacja.
Albo sam nie wie czego chce. Być może na uczelni dostał zadanie do rozwiązania w dowolnym języku programowania i szuka jeleni, którzy mu dadzą skrypt na tacy żeby mógł sobie jeszcze pobalować na wakacjach. A może jest samotną kobietą, szukającą zainteresowania u innych poprzez pisanie nieprecyzyjnych postów na forum, lub kiepskim trollem nieumiejętnie rozkręcającym flame war. Albo wysłannikiem z innego układu słonecznego, sondującym stopień rozwinięcia cywilizacji aby określić szanse powodzenia ewentualnej inwazji... Możliwości są nieskończone...

Gdzie moja kawa....

0

Poziom chamstwa w polskim Internecie, jak zwykle bardzo wysoki. Cóż, karmić trolla nie będę i pokażę kod skupiając się na temacie. Jak widać nie można zadawać ogólnych pytań bo od razu zostanie się obrzuconym gównem. Pewnie nie dowiem się jaki jest typowy sposób zabrania się za taki problem o ile sam do tego nie dojdę. Mam swój honor i nie mam zamiaru nikogo błagać - w końcu Internet to dobrodziejstwo i prędzej czy później sobie poradzę, najwyżej później niż szybciej.

  
#!/usr/bin/env ruby

# script *should* delete excessive words
# breaks white chars

def check_usage
  unless ARGV.length == 1
    puts "Usage: #{$0} filename"
    exit
  end
end

def open_file(file)
  filecontent = File.open(file).readlines
end

# proceed line and display result on standard output
def proceed_line(str)
  str = str.split
  previous = ""
  display = ""
  str.each do |element|    
    display << "#{element} " if element != previous
    previous = element
  end
  # delete excessive space
  display.chop!
  puts display  
end

# main
if $0 == __FILE__
  check_usage
  lines = open_file(ARGV[0])
  lines.each { |line| proceed_line(line) }
end

Testowe dane wejściowe:

zlo zlo		dwa
mieszkanie zlo dupa dupa dupa kwadrat
kwadrat kwadrat
bla bla bla bla
bla

Wyjście:

zlo dwa
mieszkanie zlo dupa kwadrat
kwadrat
bla
bla

Skrypt usuwa powtarzające się słowa, ale jest słaby ponieważ niszczy formatowanie. Tzn. na miejscu białego znaku zawsze pojawia się pojedyncza spacja. Jak w miejscu, gdzie były dwie spacje zachować dwie spacje, a w miejscu gdzie był inny biały znak na przykład tabulator zachować ten tabulator. Czy są na to jakieś proste sposoby?

Pozdrawiam,

2
Początkujący napisał(a)

Poziom chamstwa w polskim Internecie, jak zwykle bardzo wysoki. Cóż, karmić trolla nie będę i pokażę kod skupiając się na temacie. Jak widać nie można zadawać ogólnych pytań bo od razu zostanie się obrzuconym gównem.

Chamstwem IMHO jest wymaganie od nas, żebyśmy się domyślali co masz na myśli. Wprowadzający w błąd tytuł, niejasna i nieskładna treść oraz bardzo ogólny temat. Jeśli źle zadajesz pytanie, nie dziw się że dostajesz takie, a nie inne odpowiedzi.

Początkujący napisał(a)

Pewnie nie dowiem się jaki jest typowy sposób zabrania się za taki problem o ile sam do tego nie dojdę.

Ale problem określiłeś bardzo ogólnie i to w dodatku tak, że nie wiadomo tak właściwie o co konretnie pytasz.

Początkujący napisał(a)

Mam swój honor i nie mam zamiaru nikogo błagać - w końcu Internet to dobrodziejstwo i prędzej czy później sobie poradzę, najwyżej później niż szybciej.

Wystarczy, że sprecyzujesz pytanie (co właśnie robisz). I wyluzuj kolego. Życie jest zbyt krótkie żeby brać je na poważnie.

Początkujący napisał(a)

Skrypt usuwa powtarzające się słowa, ale jest słaby ponieważ niszczy formatowanie. Tzn. na miejscu białego znaku zawsze pojawia się pojedyncza spacja. Jak w miejscu, gdzie były dwie spacje zachować dwie spacje, a w miejscu gdzie był inny biały znak na przykład tabulator zachować ten tabulator. Czy są na to jakieś proste sposoby?

Zatem masz kod w Rubym, który nie działa tak jak tego chcesz i pytanie jest jak to naprawić. Od tego trzeba było zacząć, a nie mieszać z językami skryptowymi.
Ruby nie znam, zatem nie wypowiem się na temat kodu (spece od tego języka zaraz się odezwą). Z wyniku wnoszę jednak, że Twój skrypt splituje wejście po białych spacjach, a potem wynik skleja jedną spacją. Przy splitowaniu tracisz informację o ilości i typie białych spacji oddzielających wyrazy, więc musisz jakoś to pogodzić, np. zmieniając mechanizm splitowania lub z niego rezygnując na rzecz ręcznego parsowania.

0

W żadnej odpowiedzi nie dostrzegam śladu chamstwa. Dostałeś jasne wskazówki, że problem nie jest wystarczająco opisany. Z przykładu można się domyślać, że duplikaty to dwa identyczne słowa występujące po sobie w jednej linii. Ale nadal nie jest to pewne. Czy w tym wierszu Mama mama jest duplikat?, a w tym krowa, krowa?

0
what_i_mean_by_word = /\w+/ #zakładam że przez słowo rozumiemy zbitek liter łacińskich

contents=File.open(filename).readlines.collect! do |line|  #dla każdej linii
  uniqueWords=[]
  line.gsub!(what_i_mean_by_word) do |match|  #zamień znalezione słowo
    if uniqueWords.include?(match)
      ""                     #na pustkę(czyli usuń) jeżeli już występowało
    else
      uniqueWords.push(match)  # jak nie występowało to zapamiętaj je
      match                     #i zwróć bo nie chcemy go zmieniać
    end
  end
end

#contents zawiera zawartość pliku z formatowaniem i usuniętymi powtarzającymi się słowami w lini
0

Dzięki, wyciągne z tego wnioski na przyszłość i będę bardziej precyzyjny.

Szczególne podziękowania dla @'I hate ruby'.

1 użytkowników online, w tym zalogowanych: 0, gości: 1