Выполнить заданную разницу в списке кортежей

Я пытаюсь получить разницу между двумя контейнерами, но контейнеры имеют странную структуру, поэтому я не знаю, как лучше всего это сделать. Один тип и структуру контейнеров я не могу изменить, а другие я могу (переменные delims).

delims = ['on','with','to','and','in','the','from','or']
words = collections.Counter(s.split()).most_common()
# words results in [("the",2), ("a",9), ("diplomacy", 1)]

#I want to perform a 'difference' operation on words to remove all the delims words
descriptive_words = set(words) - set(delims)

# because of the unqiue structure of words(list of tuples) its hard to perform a difference
# on it. What would be the best way to perform a difference? Maybe...

delims = [('on',0),('with',0),('to',0),('and',0),('in',0),('the',0),('from',0),('or',0)]
words = collections.Counter(s.split()).most_common()
descriptive_words = set(words) - set(delims)

# Or maybe
words = collections.Counter(s.split()).most_common()
n_words = []
for w in words:
   n_words.append(w[0])
delims = ['on','with','to','and','in','the','from','or']
descriptive_words = set(n_words) - set(delims)

5 ответов

Решение

Как насчет просто модификации words удалив все разделители?

words = collections.Counter(s.split())
for delim in delims:
    del words[delim]

Самый простой ответ - сделать:

import collections

s = "the a a a a the a a a a a diplomacy"
delims = {'on','with','to','and','in','the','from','or'}
// For older versions of python without set literals:
// delims = set(['on','with','to','and','in','the','from','or'])
words = collections.Counter(s.split())

not_delims = {key: value for (key, value) in words.items() if key not in delims}
// For older versions of python without dict comprehensions:
// not_delims = dict(((key, value) for (key, value) in words.items() if key not in delims))

Что дает нам:

{'a': 9, 'diplomacy': 1}

Альтернативный вариант - сделать это преимущественно:

import collections

s = "the a a a a the a a a a a diplomacy"
delims = {'on','with','to','and','in','the','from','or'}
counted_words = collections.Counter((word for word in s.split() if word not in delims))

Здесь вы применяете фильтрацию к списку слов перед тем, как передать их счетчику, и это дает тот же результат.

Это я, как бы я это сделал:

delims = set(['on','with','to','and','in','the','from','or'])
# ...
descriptive_words = filter(lamdba x: x[0] not in delims, words)

Используя метод фильтра. Жизнеспособной альтернативой будет:

delims = set(['on','with','to','and','in','the','from','or'])
# ...
decsriptive_words = [ (word, count) for word,count in words if word not in delims ]

Убедиться, что delims находятся в наборе, чтобы учесть O(1) поиска.

Если вы все-таки перебираете его, зачем конвертировать их в наборы?

dwords = [delim[0] for delim in delims]
words  = [word for word in words if word[0] not in dwords]

Для производительности вы можете использовать лямбда- функции

filter(lambda word: word[0] not in delim, words)
Другие вопросы по тегам