Domanda

Ho una lista con un gran numero di righe, ciascuna prendendo forma il soggetto-verbo-oggetto, ad esempio:

Jane likes Fred
Chris dislikes Joe
Nate knows Jill

Per tracciare un grafico di rete che esprime i diversi rapporti tra i nodi bordi colorati diretti, ho bisogno di sostituire il verbo con una freccia e inserire un codice colore alla fine di ogni riga, quindi, alquanto semplificata:

Jane -> Fred red;
Chris -> Joe blue;
Nate -> Jill black;

C'è solo un piccolo numero di verbi, quindi la loro sostituzione con una freccia è solo una questione di pochi ricerca e sostituzione dei comandi. Prima di fare questo, però, ho bisogno di mettere un codice di colore alla fine di ogni riga che corrisponde al verbo della linea. Mi piacerebbe farlo utilizzando Python.

Questi sono i miei piccoli passi nella programmazione, quindi cerca di essere esplicito e comprendono il codice che legge nel file di testo.

Grazie per il vostro aiuto!

È stato utile?

Soluzione

verbs = {"dislikes":"blue", "knows":"black", "likes":"red"}
for s in open("/tmp/infile"):
  s = s.strip()
  for verb in verbs.keys():
    if (s.count(verb) > 0):
      print s.replace(verb,"->")+" "+verbs[verb]+";"
      break

Modifica: Preferisco utilizzare "per s in aperto"

Altri suggerimenti

Sembra che si vuole per la ricerca dizionari e stringa di formattazione . In generale, se hai bisogno di aiuto di programmazione, solo abbattere qualsiasi problema che avete in estremamente piccoli, pezzi discreti, cercare quei pezzi in modo indipendente, e allora si dovrebbe essere in grado di formulare il tutto in una risposta più grande. Stack Overflow è una grande risorsa per questo tipo di ricerca.

Inoltre, se avete curiosità generale su Python, cercare o navigare il documentazione ufficiale di Python . Se vi trovate costantemente senza sapere da dove cominciare, leggere il Python Tutorial o trovare un libro per passare attraverso. Una settimana o due di investimento per ottenere una buona conoscenza di base di ciò che si sta facendo pagherà più e più volte, come si completa il lavoro.

verb_color_map = {
    'likes': 'red',
    'dislikes': 'blue',
    'knows': 'black',
}

with open('infile.txt') as infile: # assuming you've stored your data in 'infile.txt'
    for line in infile:
        # Python uses the name object, so I use object_
        subject, verb, object_ = line.split()
        print "%s -> %s %s;" % (subject, object_, verb_color_map[verb])

abbastanza semplice; assumendo le liste di verbi è fisso e piccolo, questo è facile da fare con un ciclo dizionario e for:

VERBS = {
    "likes": "red"
  , "dislikes": "blue"
  , "knows": "black"
  }

def replace_verb (line):
    for verb, color in VERBS.items():
        if verb in line:
            return "%s %s;" % (
                  line.replace (verb, "->")
                , color
                )
    return line

def main ():
    filename = "my_file.txt"
    with open (filename, "r") as fp:
        for line in fp:
            print replace_verb (line)

# Allow the module to be executed directly on the command line
if __name__ == "__main__":
    main ()

Sei sicuro che questo non è un po 'homeworky :) Se è così, va bene fess up. Senza entrare troppo nel dettaglio, pensare alle attività che si sta cercando di fare:

Per ogni riga:

  1. leggerlo
  2. dividerlo in parole (su spazi - .split ())
  3. convertire la parola centrale in un colore (sulla base di una mappatura -> CF: python dict ()
  4. stampare la prima parola, freccia, terza parola e il colore

Codice utilizzando NetworkX (networkx.lanl.gov /)

'''
plot relationships in a social network
'''

import networkx
## make a fake file 'ex.txt' in this directory
## then write fake relationships to it.
example_relationships = file('ex.txt','w') 
print >> example_relationships, '''\
Jane Doe likes Fred
Chris dislikes Joe
Nate knows Jill \
'''
example_relationships.close()

rel_colors = {
    'likes':  'blue',
    'dislikes' : 'black',
    'knows'   : 'green',
}

def split_on_verb(sentence):
    ''' we know the verb is the only lower cased word

    >>> split_on_verb("Jane Doe likes Fred")
    ('Jane Does','Fred','likes')

    '''
    words = sentence.strip().split()  # take off any outside whitespace, then split
                                       # on whitespace
    if not words:
        return None  # if there aren't any words, just return nothing

    verbs = [x for x in words if x.islower()]
    verb = verbs[0]  # we want the '1st' one (python numbers from 0,1,2...)
    verb_index = words.index(verb) # where is the verb?
    subject = ' '.join(words[:verb_index])
    obj =  ' '.join(words[(verb_index+1):])  # 'object' is already used in python
    return (subject, obj, verb)


def graph_from_relationships(fh,color_dict):
    '''
    fh:  a filehandle, i.e., an opened file, from which we can read lines
        and loop over
    '''
    G = networkx.DiGraph()

    for line in fh:
        if not line.strip():  continue # move on to the next line,
                                         # if our line is empty-ish
        (subj,obj,verb) = split_on_verb(line)
        color = color_dict[verb]
        # cf: python 'string templates', there are other solutions here
        # this is the 
        print "'%s' -> '%s' [color='%s'];" % (subj,obj,color)
        G.add_edge(subj,obj,color)
        # 

    return G

G = graph_from_relationships(file('ex.txt'),rel_colors)
print G.edges()
# from here you can use the various networkx plotting tools on G, as you're inclined.

Python 2.5:

import sys
from collections import defaultdict

codes = defaultdict(lambda: ("---", "Missing action!"))
codes["likes"] =    ("-->", "red")
codes["dislikes"] = ("-/>", "green")
codes["loves"] =    ("==>", "blue")

for line in sys.stdin:
    subject, verb, object_ = line.strip().split(" ")
    arrow, color = codes[verb]
    print subject, arrow, object_, color, ";"

Oltre alla questione, Karasu anche detto (in un commento su una risposta): "In ingresso effettivo entrambi soggetti e oggetti vari imprevedibile tra uno e due parole."

Ok, ecco come vorrei risolvere questo problema.

color_map = \
{
    "likes" : "red",
    "dislikes" : "blue",
    "knows" : "black",
}

def is_verb(word):
    return word in color_map

def make_noun(lst):
    if not lst:
        return "--NONE--"
    elif len(lst) == 1:
        return lst[0]
    else:
        return "_".join(lst)


for line in open("filename").readlines():
    words = line.split()
    # subject could be one or two words
    if is_verb(words[1]):
        # subject was one word
        s = words[0]
        v = words[1]
        o = make_noun(words[2:])
    else:
        # subject was two words
        assert is_verb(words[2])
        s = make_noun(words[0:2])
        v = words[2]
        o = make_noun(words[3:])
    color = color_map[v]
    print "%s -> %s %s;" % (s, o, color)

Alcune note:

0) Non abbiamo davvero bisogno "con" per questo problema, e la scrittura in questo modo rende il programma più portabile di vecchie versioni di Python. Questo dovrebbe funzionare su Python 2.2 e successivi, credo (ho testato solo su Python 2.6).

1) È possibile modificare make_noun () per avere tutto quello strategia che ritiene più utile per la gestione di più parole. Ho mostrato solo loro concatenamento con sottolineature, ma si potrebbe avere un dizionario con aggettivi e buttare quelli fuori, hanno un vocabolario di sostantivi e scegliere quelli, o qualsiasi altra cosa.

2) Si potrebbe anche usare le espressioni regolari per la corrispondenza più confusa. Invece di semplicemente usando un dizionario per color_map si potrebbe avere una lista di tuple, con un'espressione regolare in coppia con il colore di sostituzione, e poi, quando l'espressione regolare corrisponde, sostituire il colore.

Qui è una versione migliorata della mia risposta precedente. Questo si usa corrispondenza di espressioni regolari per fare una partita confusa sul verbo. Questi tutti i lavori:

Steve loves Denise
Bears love honey
Maria interested Anders
Maria interests Anders

Il modello di espressione regolare "ama?" le partite "amore" più una 'S' facoltativa. Il modello di "interesse. *" Corrisponde a "interesse" più nulla. I modelli con più alternative separate da barre verticali corrispondono se uno qualsiasi delle alternative partite.

import re

re_map = \
[
    ("likes?|loves?|interest.*", "red"),
    ("dislikes?|hates?", "blue"),
    ("knows?|tolerates?|ignores?", "black"),
]

# compile the regular expressions one time, then use many times
pat_map = [(re.compile(s), color) for s, color in re_map]

# We dont use is_verb() in this version, but here it is.
# A word is a verb if any of the patterns match.
def is_verb(word):
    return any(pat.match(word) for pat, color in pat_map)

# Return color from matched verb, or None if no match.
# This detects whether a word is a verb, and looks up the color, at the same time.
def color_from_verb(word):
    for pat, color in pat_map:
        if pat.match(word):
            return color
    return None

def make_noun(lst):
    if not lst:
        return "--NONE--"
    elif len(lst) == 1:
        return lst[0]
    else:
        return "_".join(lst)


for line in open("filename"):
    words = line.split()
    # subject could be one or two words
    color = color_from_verb(words[1])
    if color:
        # subject was one word
        s = words[0]
        o = make_noun(words[2:])
    else:
        # subject was two words
        color = color_from_verb(words[1])
        assert color
        s = make_noun(words[0:2])
        o = make_noun(words[3:])
    print "%s -> %s %s;" % (s, o, color)

Spero che sia chiaro come prendere questa risposta ed estenderlo. Si può facilmente aggiungere ulteriori modelli per abbinare altri verbi. Si potrebbe aggiungere la logica per rilevare "è" e "in" e gettarli, in modo che "Anders è interessato a Maria" sarebbe partita. E così via.

Se avete domande, sarei felice di spiegare questo ulteriore. Buona fortuna.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top