2012-03-29 2 views
0

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

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) 

ответ

3

Как насчет изменения words, удалив все разделители?

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

, который выглядит эффектно Я думаю, что буду использовать его, но слова - это список кортежей, как я могу сказать «слова [delim]»? –

+0

@JakeM - применить его непосредственно к объекту Counter. – eumiro

+0

Ах, я думал, что это был объект Counter –

1

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

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) lookup.

+0

Первый метод использует «in», означает ли это, что каждое сравнение мы повторяем во всех делимах? –

+0

нет, если они набор или диктофон. O (1), [документы говорят] (http://wiki.python.org/moin/TimeComplexity). – brice

0

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

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

@Rob Молодой да, я стараюсь избегать итерации над ними для повышения эффективности. Любое решение, которое не выполняет итерацию, лучше всего, я думаю –

+0

Плохая идея. Это было бы O (n^2), не так ли? – brice

0

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

filter(lambda word: word[0] not in delim, words) 
+0

фильтр + лямбда менее читабельна, чем понимание списка, и понимание списка может [часто быть быстрее] (http://wiki.python.org/moin/PythonSpeed/PerformanceTips# Loops). –

+0

Во-вторых, это все еще делает O (n^2), поскольку delims - это список. – brice

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'} 
// 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)) 

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