2014-11-19 2 views
0

У меня есть список питов int, a. У меня также есть другой список, b, который является кортежем из 2 значений (c, d). Мне нужно выяснить, имеют ли какие-либо элементы a значения, которые находятся между любыми элементами кортежа b.Python - применить условную функцию (пересечение) к каждому элементу списка

I думаю есть способ сделать это используя map(), но я не могу понять, как передать значения моего списка кортежей.

Например, моя структура данных выглядит следующим образом:

a = [1, 2, 3, 4, 5, 6, 7] 
b = [(12,14), (54, 78), (2,3), (9,11)] 

Я пытаюсь выяснить, если какие-либо из элементов a имеет значение между любым из кортежа элементов b. В приведенном выше случае 2 и 3 (от a) находятся внутри (включительно) кортежа (2,3) в b. Поэтому мой последний ответ будет True.

Есть ли у кого-нибудь идеи, как это сделать в исполнении? Прямо сейчас, я перебираю каждый элемент из a, а затем перебираю каждый элемент из b. Это нормально для небольших объемов данных, но мои массивы довольно велики, и этот шаг подходит к концу.

+2

Я не думаю, что это будет способ сделать это для произвольных данных, не зацикливая на все.Вы можете попытаться выполнить оптимизацию, например, препроцессор «b», чтобы найти общий макс и минус, а затем исключить значения из 'a', которые находятся за пределами этого диапазона, но будет ли это улучшаться, зависит от того, что такое данные. – BrenBarn

+2

Может ли кортеж в 'b' перекрываться? то есть 'b = [(1, 5), (3, 7)]' возможно? Иными словами, вы ожидаете, что будет один кортеж, определяющий диапазон, в котором '' 'находится внутри, или может быть несколько? – Stuart

+0

Также являются значениями всех целых чисел в определенном диапазоне? – Stuart

ответ

1

dId вы хотите это?

[c in range(k[0], k[1]+1) for c in a for k in b] 

возвращается:

[False, False, False, False, # 1 is in any ofthe tuple range in b? 
False, False, True, False, # 2 is in any of the tuple range in b? 
False, False, True, False, # etc. etc.... 
False, False, False, False, 
False, False, False, False, 
False, False, False, False, 
False, False, False, False] # searches for each element in a within the range specified by the tuple elements in b 

Если вы хотите сделать что-то другое, как проверка каждый элемент в использовании каждого элемента б первый затем поменять порядок for с:

[c in range(k[0], k[1]+1) for k in b for c in a] 

Доходы:

[False, False, False, False, False, False, False, // is b[0] range covers 1-7? 
False, False, False, False, False, False, False, // etc. etc. 
False, True, True, False, False, False, False, 
False, False, False, False, False, False, False] 

Я предположил, что это то, что вы не хотите .... но думал, что я бы отправить его к вам все равно

+0

Это прекрасно. Я последовал за ним с помощью 'any()', чтобы получить один «True» или «False», который подходит для моего прецедента. – Brett

+0

Это проходит через каждый элемент a, а затем проходит через каждый элемент b. Я думал, это то, чего вы пытались избежать ...? – Stuart

+0

Извините за то, что вы предоставили вам половину рабочего решения, поскольку я знаю, сколько вы захотите, чтобы каждая из строк указывала, какой номер в нем ему удалось сопоставить. – ha9u63ar

1

Если значения (c, d) ограничены определенным диапазоном (скажем, 0-100), вы можете вычислить логический массив допустимых значений и сравнить их с простым поиском индекса.

Если вы не ограничены или диапазон слишком велик, поместите значения b в отсортированную структуру данных. Тогда вы можете быстро взглянуть на него, без необходимости каждый раз просматривать весь список. При построении этой структуры данных поиска вам придется искать перекрывающиеся диапазоны и объединять их.

1

При сортировке первых, вы можете избежать проверки каждого значения в a против каждого кортежа в b. Кортежи, которые уже были проверены на более низкие значения a, могут быть отброшены, что сделает проверку намного быстрее.

def check_value_in_ranges(a, b): 
    a = sorted(set(a)) 
    b = sorted(set(b), reverse=True) 
    lower, upper = b.pop() 
    for value in a: 
     while value >= lower: 
      if value <= upper: 
       return True 
      elif not b:     
       return False   # no tuples left to check against 
      lower, upper = b.pop()  
    return False      # no values of a left to check 

Я думаю, что это работает ли кортежи накладываются друг на друга или нет - check here.

Смежные вопросы