Listor, Python. Behöver förklaring till vissa saker.

Permalänk
Medlem

Listor, Python. Behöver förklaring till vissa saker.

Hejsan,

Jag sitter med en uppgift som handlar om listor, vad som händer i programmet har jag faktiskt ingen aning om. Har försökt ändra kod flera gånger för att försöka förstå vad som händer, men det är tomt.

Jag har följande text: "hello therer! this is a text string, actually really sundelly peruchally this is another string. this is a text string."
Jag ska med hjälp av denna texten hitta alla ord som förekommer mer än en gång, och sedan märka dem med t.ex. #ord#, detta har jag lyckats med.
Detta gjorde jag genom att ta bort alla ",.!?" sedan gjorde jag om alla tecken till gemener, så att jag kunde jämföra orden i en for-loop.

Nu vill jag istället skriva dit ".,!?" på det stället där de förekom i originaltexten (fast i den nya listan)
Min tanke var att göra på samma sätt: splittar båda listorna med hjälp av t.ex. a = list(text1) och b = list (text2)

För att sedan jämföra varje position i listan så körde jag ytterligare en for-loop.
for tecken in a:
if tecken not in b:
b.append(tecken)

Denna metod verkar inte fungera, och jag verkar inte kunna förstå varför.

Hoppas jag var tillräckligt tydlig med mitt problem.

Permalänk
Medlem

Tror det är lättare om du aldrig tar bort tecknen ",.!?". Gör du det måste du ha någon sorts index och en ny lista där du lagrar tecknen du tar bort.

Kan du inte i stället när du jämför ord bortse från ",.!?" och säga att strängarna "this" och "this," är likadana?

Permalänk
Medlem

Det borde helt klart vara möjligt.

Men har ingen aning om hur man går till väga, eller vad det ens heter (om det finns inbyggt metod i python som behandlar sådant)

Permalänk
Medlem

Pseudokod för problemet fast med ord kan vara:

Gå igenom texten och identifiera alla ord och lagra dem i en lista (kallar den listan för ordLista)

Gå igenom ordLista för att hitta de ord som är dubletter. Spara alla ord som är dubletter i en ny lista (kallar den för dublettLista).

Gå igenom texten igen och identifiera alla ord du hittar och jämför dem med orden i dublettLista. Ord som är likadana ersätter du med #ord#.

Inser att mina idéer kanske inte är så lätta att förklara här men det är alltid något

Permalänk
Medlem

Jag har i princip 3 olika lister.

Originaltexten i en lista (med rätt tecken)
text 2 (En lista med alla dubletter utan tecken och alla i små bokstäver)
text3 (En lista med alla tecken på rätt ställe, stor bokstav efter punkt och alla dubbletter är markerade FÖRUTOM!!! t.ex. äpplet, och äpplet. eller Han och han (dessa saker ser programmet som olika, och det är det jag måste fixa)

Så jag har "löst" uppgiften var för sig, men att sätta ihop dessa går mindre bra.

Och det är som du sa, problemet är äpplet, inte är lika med äpplet.

I brist på idéer var jag inne och kollade på metoder som re.sub (verkar finnas många smarta saker) men det var helt obegripligt.

Permalänk
Medlem

Tycker det ser ut som du är på rätt väg med de där listorna. Kan inte python så kan inte tipsa om metoder.

kankse är överkurs för ditt problem men vet iaf att en av de bästa sätten att jämföra strängar är med reguljära utryck.

t.ex utrycket [\s,.] matchar alla tecken som t.ex "!,.?"

https://docs.python.org/2/howto/regex.html

Permalänk
Datavetare

Skulle nog skapa en funktion som går igenom strängen och sekventiellt delar upp den i ord och annan text. T.ex. så här

TOK_ALPHA = "A" TOK_OTHER = "O" TOK_SENTINEL = "#" def toktype(c): if str.isalpha(c): return TOK_ALPHA return TOK_OTHER def word_accumulator(toks, c): tt = toktype(c) if toks[-1][0] == tt: # Same token as previous character, append to existing string toks[-1] = (tt, toks[-1][1] + c.lower()) else: # New type of token, add new entry toks.append((tt, c)) return toks def parse(s): return reduce(word_accumulator, s, [(TOK_SENTINEL, None)])[1:] s = "hello therer! this Is a text string, actually really sundelly peruchally this is another string. this is a text string." print parse(s)

Kör man detta får man

[('A', 'hello'), ('O', ' '), ('A', 'therer'), ('O', '! '), ('A', 'this'), ('O', ' '), ('A', 'Is'), ('O', ' '), ('A', 'a'), ('O', ' '), ('A', 'text'), ('O', ' '), ('A', 'string'), ('O', ', '), ('A', 'actually'), ('O', ' '), ('A', 'really'), ('O', ' '), ('A', 'sundelly'), ('O', ' '), ('A', 'peruchally'), ('O', ' '), ('A', 'this'), ('O', ' '), ('A', 'is'), ('O', ' '), ('A', 'another'), ('O', ' '), ('A', 'string'), ('O', '. '), ('A', 'this'), ('O', ' '), ('A', 'is'), ('O', ' '), ('A', 'a'), ('O', ' '), ('A', 'text'), ('O', ' '), ('A', 'string'), ('O', '.')]

Nu har du en lista där det går att särskilja ord från annat utan att något är bortplockat, det som nu behövs göras är att räkna hur många ord som är lika (och hoppa över allt som inte är ord).

Sedan filtrerar man bort alla ord som det inte finns mer än ett av (detta har du ju redan gjort).

Nu kan du kombinera listan med duplicerade ord med listan parse() skapade och återskapa ursprungssträngen genom att iterera över listan från parse(). Är typen 'O' så är det bara lägga till strängen, är typen 'A' och ordet inte är duplikat lägger man också bara till den. Annars markeras ordet på önskat sätt och man lägger till ord + markering.

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem
Skrivet av Atr0x:

Jag har i princip 3 olika lister.

Originaltexten i en lista (med rätt tecken)
text 2 (En lista med alla dubletter utan tecken och alla i små bokstäver)
text3 (En lista med alla tecken på rätt ställe, stor bokstav efter punkt och alla dubbletter är markerade FÖRUTOM!!! t.ex. äpplet, och äpplet. eller Han och han (dessa saker ser programmet som olika, och det är det jag måste fixa)

Så jag har "löst" uppgiften var för sig, men att sätta ihop dessa går mindre bra.

Och det är som du sa, problemet är äpplet, inte är lika med äpplet.

I brist på idéer var jag inne och kollade på metoder som re.sub (verkar finnas många smarta saker) men det var helt obegripligt.

Som exempel på hur man kan använda re.sub är här kod för att lösa ditt första problem (att skriva "#" före och efter ord som förekommer fler än en gång):

import re text = "hello therer! this is a text string, actually really sundelly peruchally this is another string. this is a text string." parts = [x.lower() for x in re.split("\W+", text)] def replace(match): str = match.group(0) if parts.count(str.lower()) > 1: return "#" + str + "#" return str print(re.sub("\w+", replace, text))

Permalänk
Medlem

Tack för era svar! Ska pröva imorgon!

Inte för att vara krånglig nu, (jag gör ju ändå detta för att lära mig)

men låt oss säga att vi skulle vilja jämföra alla tecken i två listor med hjälp av en for-sats och sedan lägga till ¨den lista där tecknen saknas

dvs.

För att sedan jämföra varje position i listan så körde jag ytterligare en for-loop.
for tecken in a:
if tecken not in b:
b.append(tecken)

Varför lägger sig tecknen längst bak?
Borde inte denna for-sats jämföra plats 1, kolla om tecknet är samma, gå vidare till plats 2 osv.
När den väl kommer till (låt oss säga) plats 37 så finns det en . i lista 1 men inte i två.
Varför läggs inte då punkten till i plats 37 i lista 2?

:/

Permalänk
Medlem

Testa detta

import re string = "hello therer! this!!! isa A,,, Text string, actually really sundelly peruchally This is another string. this is a text string." lista = string.split(' ') final = [] for x,cur_ord in enumerate(lista): count = 0 lista2 = lista for line in (lista2): k = cur_ord.translate(None, ',!?.').lower() y = line.translate(None, ',!?.').lower() if k == y: count += 1 if count > 1: m = re.search('([!|\?|\.\,]+)', cur_ord) if m: char = m.group(1) else: char = '' cur_ord = ('#%s#%s') % (cur_ord.translate(None, ',!?.'),char) final.append(cur_ord) else: final.append(cur_ord) print ' '.join(final)

Sorry för alla fula variabelnamn

Permalänk
Medlem
Skrivet av Atr0x:

Tack för era svar! Ska pröva imorgon!

Inte för att vara krånglig nu, (jag gör ju ändå detta för att lära mig)

men låt oss säga att vi skulle vilja jämföra alla tecken i två listor med hjälp av en for-sats och sedan lägga till ¨den lista där tecknen saknas

dvs.

För att sedan jämföra varje position i listan så körde jag ytterligare en for-loop.
for tecken in a:
if tecken not in b:
b.append(tecken)

Varför lägger sig tecknen längst bak?
Borde inte denna for-sats jämföra plats 1, kolla om tecknet är samma, gå vidare till plats 2 osv.
När den väl kommer till (låt oss säga) plats 37 så finns det en . i lista 1 men inte i två.
Varför läggs inte då punkten till i plats 37 i lista 2?

:/

Append lägger alltid variabeln sist i en list.
Sedan så jämför inte din kod plats 1 i A med plats 1 i b.
plats 1 i A kommer itereras i hela B för att kolla om den finns någonstans i B.

du kan använda list.insert(x, var) för att putta in variablar på en specifik plats i en list.

Permalänk
Medlem
Skrivet av CloX:

Append lägger alltid variabeln sist i en list.
Sedan så jämför inte din kod plats 1 i A med plats 1 i b.
plats 1 i A kommer itereras i hela B för att kolla om den finns någonstans i B.

du kan använda list.insert(x, var) för att putta in variablar på en specifik plats i en list.

Ah! för jag körde append när jag jämförde originallistan (utan tecken och gemener) med en lista som jag kallade Ny.
Den Nya listan (Ny) var ju iofs tom från början, vilket innebär att ordet lades ju hela tiden på efter det förra året! Och därför stämde det med mina dubbletter och stora bokstäver!

Jag borde väl också kunna köra en re.sub på min lista som inte känner igen appel. och appel, om man bortser från tecken vid ord genom typ \W? eller \b? eller något sådant. (måste kolla upp det mer noggrant)

Tack!

Permalänk
Medlem
Skrivet av grovlimpa:

Som exempel på hur man kan använda re.sub är här kod för att lösa ditt första problem (att skriva "#" före och efter ord som förekommer fler än en gång):

import re text = "hello therer! this is a text string, actually really sundelly peruchally this is another string. this is a text string." parts = [x.lower() for x in re.split("\W+", text)] def replace(match): str = match.group(0) if parts.count(str.lower()) > 1: return "#" + str + "#" return str print(re.sub("\w+", replace, text))

Nu ska vi se om jag förstår koden rätt:

parts gör så att text kommer splittas m.h.a re.split. "\W+" = Matches any character which is not a Unicode word character.? Men vad betyder +-tecknet efter W?

Sen skapas en funktion som heter replace som har ett ingångsvärde som heter match. Var kommer match ifrån? Är det standard?
Sen blir str = antal som matchar.
I if-satsen så kommer den returnera #str# om antalet är större än 1.
annars returnerar den bara str.

sedan skrivs allt ut.

MEN problemet är att alla dubbletter skrivs ut, inte bara de som förekommer mer än en gång. Skulle man kunna ta alla dubbletter och lägga de i en lista, sedan ta den nya listan - dubbletterna? Så att den skriver ut alla dubbletter om de förekommer mer än en gång. (dvs apples APPELS APPELS)

Permalänk
Medlem
Skrivet av Atr0x:

Jag ska med hjälp av denna texten hitta alla ord som förekommer mer än en gång, och sedan märka dem med t.ex. #ord#, detta har jag lyckats med.
Detta gjorde jag genom att ta bort alla ",.!?" sedan gjorde jag om alla tecken till gemener, så att jag kunde jämföra orden i en for-loop.

Nu vill jag istället skriva dit ".,!?" på det stället där de förekom i originaltexten (fast i den nya listan)
Min tanke var att göra på samma sätt: splittar båda listorna med hjälp av t.ex. a = list(text1) och b = list (text2)

Om du ska kolla efter dubbletter skulle du kunna använda listmetoden count.
Om du tar den långa texten du använder och gör en lista av den med strängmetoden split så kan du sedan köra en for loop genom listan och för varje ord du stöter på så kör du en count så att du ser om den är över 1.
Om den inte är en dubblett, lägg till den i en ny lista helt normalt med append. Är den en dubblett, lägg till # på det sätt du ville innan du appendar den till den nya listan.

string_x = "a b c d a" list_x = string_x.split() newlist = [] for word in list_x: if list_x.count(word) > 1: word = "#" + word + "#" newlist.append(word) else: newlist.append(word) print string_x print list_x print newlist

Visa signatur

/M

Permalänk
Medlem
Skrivet av Marowak:

Om du ska kolla efter dubbletter skulle du kunna använda listmetoden count.
Om du tar den långa texten du använder och gör en lista av den med strängmetoden split så kan du sedan köra en for loop genom listan och för varje ord du stöter på så kör du en count så att du ser om den är över 1.
Om den inte är en dubblett, lägg till den i en ny lista helt normalt med append. Är den en dubblett, lägg till # på det sätt du ville innan du appendar den till den nya listan.

string_x = "a b c d a" list_x = string_x.split() newlist = [] for word in list_x: if list_x.count(word) > 1: word = "#" + word + "#" newlist.append(word) else: newlist.append(word) print string_x print list_x print newlist

Jo, problematiken här är att du varken tar hänsyn till gemener/versaler, eller specialtecken såsom punkt och utropstecken. Men visst du kan använda stringmethod lower så är iaf det ena problemet löst. Men inte det andra.

Permalänk
Medlem

Har inte jobbat så mycket med uppgiften på ett bra tag nu.
Men lyckades i alla fall fixa så att alla !.,"=-tecken är på rätt ställe med rätt mellanrum, samt att alla bokstäver som är versaler även är det i min text (t.ex. namn osv)

Problemet är att "Han" och "han" inte är lika, jag har en teori om varför lite längre ned.

for word in text2:

if word.lower() not in Ny_OrdLista:
Ny_OrdLista.append(word)
elif word.lower() in Ny_OrdLista:
Ny_OrdLista.append(word.upper())

Problemet med kodsnuten ovan är om man har t.e.x. texten.

"Han gillar att äta äpplen, han åt 4 äpplen igår."

Det första "Han" finns inte i Ny_OrdLista, därför kommer "Han" att läggas till. När programmet sedan kommer till ordet "han" så finns inte det heller i ordlistan, därför kommer även det läggas till i if-satsen, även fast det borde hamna under elif.

Skulle det istället stått:

"Jag tycker att han gillar äpplen. Han gillar nog äpplen" Så skulle programmet dock fungerat.

Lite osäker på hur man lättast löser det dock.

Permalänk
Medlem

Du har redan en lista med alla ord.
Skapa två nya listor, en för ett av varje ord och en för dubletter.

Loopa igenom listan med alla ord. Om ordet.lower() finns i listan med ett av varje ord och ordet.lower() inte finns med i listan med dubletter så lägger du till ordet.lower() i listan med dubletter annars så lägger du till ordet.lower() i listan med ett av varje ord.

När du loopat igenom listan med alla ord så kan du använda listan med dubletter.

Visa signatur

I'm Winston Wolfe. I solve problems.

Permalänk
Medlem
Skrivet av matti4s:

Du har redan en lista med alla ord.
Skapa två nya listor, en för ett av varje ord och en för dubletter.

Loopa igenom listan med alla ord. Om ordet.lower() finns i listan med ett av varje ord och ordet.lower() inte finns med i listan med dubletter så lägger du till ordet.lower() i listan med dubletter annars så lägger du till ordet.lower() i listan med ett av varje ord.

När du loopat igenom listan med alla ord så kan du använda listan med dubletter.

Jag har varit inne på det tidigare faktiskt, men fick det inte riktigt att fungera.
Ska ta en ny titt på det!