Поместите bar в конце каждой строки, содержащей foo.
-
19-09-2019 - |
Вопрос
У меня есть список с большим количеством строк, каждая из которых имеет форму субъект-глагол-объект, например:
Jane likes Fred Chris dislikes Joe Nate knows Jill
Чтобы построить сетевой граф, который выражает различные отношения между узлами в направленных ребрах с цветовой кодировкой, мне нужно будет заменить глагол стрелкой и поместить цветовой код в конце каждой строки, что несколько упростит:
Jane -> Fred red; Chris -> Joe blue; Nate -> Jill black;
Глаголов немного, поэтому замена их стрелкой — это всего лишь вопрос нескольких команд поиска и замены.Однако прежде чем сделать это, мне нужно будет поместить в конце каждой строки цветовой код, соответствующий глаголу строки.Я хотел бы сделать это с помощью Python.
Это мои первые шаги в программировании, поэтому, пожалуйста, будьте откровенны и включите код, который читается в текстовом файле.
Спасибо за вашу помощь!
Решение
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
Редактировать:Лучше используйте «for s in open»
Другие советы
Похоже, вы захотите изучить словари и форматирование строк.В общем, если вам нужна помощь в программировании, просто разбейте любую возникшую у вас проблему на очень маленькие, отдельные фрагменты, выполните поиск по этим фрагментам независимо, а затем вы сможете сформулировать все это в более крупный ответ.Stack Overflow — отличный ресурс для такого типа поиска.
Кроме того, если у вас есть какие-либо общие вопросы о Python, найдите или просмотрите официальная документация Python.Если вы постоянно не знаете, с чего начать, прочитайте Учебник по Python или найдите книгу, которую можно прочитать.Неделя или две, потраченные на получение хороших базовых знаний о том, что вы делаете, окупятся снова и снова по мере завершения работы.
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])
Достаточно просто;предполагая, что списки глаголов фиксированы и малы, это легко сделать с помощью словаря и 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 ()
Вы уверены, что это не домашнее задание :) Если да, то можно сознаться.Не вдаваясь в подробности, подумайте о задачах, которые вы пытаетесь выполнить:
Для каждой строки:
- прочти это
- разделить его на слова (по пробелам - .split() )
- преобразовать среднее слово в цвет (на основе сопоставления -> ср.:Python дикт()
- напечатайте первое слово, стрелку, третье слово и цвет
Код с использованием 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.
Питон 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, ";"
В дополнение к вопросу Карасу также сказал (в комментарии к одному ответу):«При фактическом вводе и субъекты, и объекты непредсказуемо изменяются от одного до двух слов».
Хорошо, вот как я бы это решил.
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)
Некоторые примечания:
0) На самом деле для этой задачи нам не нужно слово «с», и его написание таким образом делает программу более переносимой для старых версий Python.Я думаю, это должно работать на Python 2.2 и новее (я тестировал только на Python 2.6).
1) Вы можете изменить make_noun(), чтобы использовать любую стратегию, которую вы считаете полезной для обработки нескольких слов.Я показал, как просто соединяю их вместе с помощью подчеркивания, но вы можете иметь словарь прилагательных и выбрасывать их, иметь словарь существительных и выбирать их или что-то еще.
2) Вы также можете использовать регулярные выражения для более нечеткого сопоставления.Вместо того, чтобы просто использовать словарь для color_map, вы могли бы иметь список кортежей с регулярным выражением в паре с заменяющим цветом, а затем, когда регулярное выражение совпадет, заменить цвет.
Вот улучшенная версия моего предыдущего ответа.В этом случае используется сопоставление регулярных выражений для получения нечеткого совпадения глагола.Все это работает:
Steve loves Denise
Bears love honey
Maria interested Anders
Maria interests Anders
Регулярный рисунок выражения "любит?" соответствует "Love" плюс необязательный 's'.Шаблон «interest.*» соответствует «interest» плюс что-нибудь еще.Шаблоны с несколькими альтернативами, разделенными вертикальными полосами, соответствуют, если соответствует хотя бы одна из альтернатив.
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)
Надеюсь, понятно, как взять этот ответ и расширить его.Вы можете легко добавить больше шаблонов, чтобы соответствовать большему количеству глаголов.Вы можете добавить логику для определения «есть» и «в» и отбросить их, чтобы совпадало «Андерс интересуется Марией».И так далее.
Если у вас есть какие-либо вопросы, я буду рад объяснить это подробнее.Удачи.