2014-12-16 2 views
2

У меня есть следующий код:Создать набор из элементов в двух списках

ids = set() 
for result in text_results: 
    ids.add(str(result[5])) 
for result in doc_results: 
    ids.add(str(result[4])) 

Оба text_results и doc_results списки, содержащие другие списки как элементы, как вы, возможно, уже догадались. Есть ли более эффективный способ сделать это, используя отличные oneliner, а не два для циклов?

+3

Что ваша мотивация для желающих Однострочник? Я считаю, что текущий код отлично читаем. – NPE

+0

Ваш код хорош как есть. Один лайнер не лучше во всех случаях. – jamylak

+0

@NPE. Я не строго настроен на однострочный, но сокращение его до двух строк кажется мне разумным. – mart1n

ответ

4

Я бы, наверное, написать:

ids = set(str(result[5]) for result in text_results) 
ids.update(str(result[4]) for result in doc_results) 

Что касается эффективности, если вы хотите, чтобы выжать все возможные немного производительности, то в первую очередь необходимо реалистичный набор данных, то вы можете попробовать такие вещи, как map (или itertools.imap в Python 2) и operator.itemgetter, чтобы узнать, что быстрее.

Если вам абсолютно необходимо иметь один вкладыш:

ids = set(itertools.chain((str(result[5]) for result in text_results), (str(result[4]) for result in doc_results))) 

Хотя, если вы хотите Однострочник это также стоит оптимизации для лаконичности, чтобы ваш один лайнер будет читаться, а затем, видя ли достаточная производительность:

ids = set([str(x[5]) for x in text_results] + [str(x[4]) for x in doc_results])) 

Это «чувствует» неэффективность, потому что оно объединяет два списка, которые не должны быть необходимы. Но это не означает, что это действительно неэффективно для ваших данных, поэтому его ценность в том числе и в ваших тестах.

+0

Мне нравится ваше первое решение. Спасибо, это выглядит лучше. – mart1n

0

Это один лайнер должен работать:

ids = set(map (lambda x: str(x[4]), doc_results) + map(lambda x: str(x[5]), text_results)) 
+4

Однострочный? Определенно. Улучшение оригинала? Я лично не так уверен. – NPE

+0

@NPE, я думаю, что создание набора из списка возможно быстрее, чем добавление к нему по одному: http://stackoverflow.com/questions/5835657/performance-comparison-insert-vs-build-python-set- операции –

+0

@ReutSharabani Как насчет стоимости создания списка? –

0

Это (завернутые) один лайнер должен работать:

ids = set([str(tr[5]) for tr in text_results] + 
      [str(dr[4]) for dr in doc_results]) 
0

ли это:

ids = {str(i) for text, doc in zip(text_results, doc_results) for i in (text[5], doc[4])} 

Это предполагает, что результаты что-то вроде :

text_results = [['t11', 't12', 't13', 't14', 't15', 't16'], ['t21', 't22', 't23', 't24', 't25', 't26']] 
doc_results = [['d11', 'd12', 'd13', 'd14', 'd15', 'd16'], ['d21', 'd22', 'd23', 'd24', 'd25', 'd26']] 

И вы хотите:

ids = {'d15', 't26', 't16', 'd25'} 
+0

Установить понимание доступно на python 2: https://docs.python.org/2/tutorial/datastructures.html –

0

Я думаю, что это более вещий путь:

map(str,set([i[5] for i in text_results]+[i[4] for i in doc_results])) 

Демо:

>>> text_results = [[1,2,3,4,5,6,7,8,9],[1,2,3,4,56,6],[4,5,6,1,2,6,22],[1,2,3,4,5,7,8,9]] 
>>> doc_results = [[1,2,3,4,5,9,7,8,9],[1,2,3,4,56,3],[4,5,6,1,2,7,22],[1,2,3,4,5,7,7,9]] 
>>> map(str,set([i[5] for i in text_results]+[i[4] for i in doc_results])) 
['56', '2', '5', '6', '7'] 
Смежные вопросы