簡體   English   中英

在Python 3中獲取2個列表之間的交集

[英]Getting Intersection Between 2 Lists in Python 3

我有一個應用程序,其中包含對象列表( answers ),每個對象包含一個稱為spaces的元組列表。 我正在嘗試編寫一個在所有spaces列表之間生成公用項目列表的函數。 此列表中的每條記錄應為[(answer,index), (answer, index)] (這是一種填字游戲風格的程序,需要標識所有答案之間的公共空格)。

目前,我的代碼如下:

for answer in answers:
    for compareAnswer in answers:
        if( answer != compareAnswer ):
            for compareSpace in compareAnswer.spaces:
                if compareSpace in answer.spaces:
                    intersect.append( [( answer, answer.spaces.index(compareSpace) ), ( compareAnswer, compareAnswer.spaces.index(compareSpace) ) ] );

該代碼按預期工作; 但是,我覺得可能有更簡單的方法可以到達目的地。 有沒有更多的pythonic(或至少更容易閱讀)的方式來做到這一點? 謝謝。

完整程序代碼:

import os
import random

def printList( toPrint ):
    for line in toPrint:
        print( line )
    print("---------------------")

#
#
#
class Answer:
    def __init__( self, num, ad, length, y, x ):
        self.num = num
        self.ad = ad
        self.length = length
        self.spaces = []
        if( ad == 'A' ):
            for occupied in range(length):
                self.spaces.append( (y,x) )
                x += 1
        if( ad == 'D' ):
            for occupied in range(length):
                self.spaces.append( (y,x) )
                y += 1              
        self.domain = []
        self.intersect = []
        self.value = " " * length

    def SetDomain( self, dictionary ):
        for poss in dictionary:
            if( len( poss ) == self.length ):
                self.domain.append( poss )

#
#
#
puzPath = os.getcwd() + "\input.txt"
dictPath = os.getcwd() + "\dictionary.txt"

puzzle = []
dictionary = []
count = 0
answers = []
intersect = []

#Read files for puzzle and dictionary
with open(puzPath,'r') as puzFile:
    puzzle = [list(line.strip()) for line in puzFile]

with open(dictPath,'r') as dictFile:
    dictionary = [line.strip() for line in dictFile]

#Add border to eliminate out of bounds errors
size = len(puzzle[0])
border = ['X']*size
puzzle.insert(0, border)
puzzle.append(border)
puzzle = [['X'] + line + ['X'] for line in puzzle]

#Number board and set variables
for y in range(1, len(puzzle)-1):
    for x in range(1, len(puzzle[0])-1):
        if ( puzzle[y][x] == 'O' ):
            downStart = False
            acrossStart = False
            if ( puzzle[y-1][x] == 'X' and puzzle[y+1][x] != 'X' ):
                downStart = True
            if ( puzzle[y][x-1] == 'X' and puzzle[y][x+1] != 'X' ):
                acrossStart = True
            if ( downStart or acrossStart ):
                count+=1

            if( acrossStart ):
                puzzle[y][x] = count
                length = 1
                while( puzzle[y][x+length] != 'X' ):
                    length += 1
                answers.append( Answer( count, "A", length, y, x ) )
            if( downStart ):
                puzzle[y][x] = count
                length = 1
                while( puzzle[y+length][x] != 'X' ):
                    length += 1
                answers.append( Answer( count, "D", length, y, x ) )

#Set domain & contstraints for all variables
for answer in answers:
    answer.SetDomain( dictionary )
    for compareAnswer in answers:
        if( answer.ad != compareAnswer.ad ):
            for compareSpace in compareAnswer.spaces:
                if compareSpace in answer.spaces:
                    intersect.append( [( answer, answer.spaces.index(compareSpace) ), ( compareAnswer, compareAnswer.spaces.index(compareSpace) ) ] );

示例答案空間:

[(1, 1), (1, 2), (1, 3), (1, 4)]
---------------------
[(1, 1), (2, 1), (3, 1)]
---------------------
[(1, 3), (2, 3), (3, 3)]
---------------------
[(1, 6), (1, 7), (1, 8), (1, 9)]
---------------------
[(1, 7), (2, 7), (3, 7)]
---------------------
[(1, 9), (2, 9), (3, 9)]
---------------------
[(3, 1), (3, 2), (3, 3), (3, 4)]
---------------------
[(3, 2), (4, 2), (5, 2), (6, 2), (7, 2)]
---------------------
[(3, 4), (4, 4), (5, 4), (6, 4), (7, 4)]
---------------------
[(3, 6), (3, 7), (3, 8), (3, 9)]
---------------------
[(3, 6), (4, 6), (5, 6), (6, 6), (7, 6)]
---------------------
[(3, 8), (4, 8), (5, 8), (6, 8), (7, 8)]
---------------------
[(4, 4), (4, 5), (4, 6)]
---------------------
[(5, 1), (5, 2), (5, 3), (5, 4)]
---------------------
[(5, 6), (5, 7), (5, 8), (5, 9)]
---------------------
[(6, 4), (6, 5), (6, 6)]
---------------------
[(7, 1), (7, 2), (7, 3), (7, 4)]
---------------------
[(7, 1), (8, 1), (9, 1)]
---------------------
[(7, 3), (8, 3), (9, 3)]
---------------------
[(7, 6), (7, 7), (7, 8), (7, 9)]
---------------------
[(7, 7), (8, 7), (9, 7)]
---------------------
[(7, 9), (8, 9), (9, 9)]
---------------------
[(9, 1), (9, 2), (9, 3), (9, 4)]
---------------------
[(9, 6), (9, 7), (9, 8), (9, 9)]

如果n是答案數, m是每個答案中的空格數,則代碼的時間復雜度為O(n*n*m*m*m) ,可以改善,例如,這里的O(n*m)算法:

from collections import defaultdict

spaces = defaultdict(list) # space -> [(answer1, index1), (answer2, index2), ...]
for answer in answers:
    for i, space in enumerate(answer.spaces): 
        spaces[space].append((answer, i)) 
intersections = [occurrences for occurrences in spaces.values()
                 if len(occurrences) > 1]

與您的代碼一樣,它假定每個空格在一個答案中出現一次。 與您的代碼不同,在空格的不同答案中所有出現的事件都在intersections列表中分組在一起。

您可以在python3中使用集合和交集來獲取兩個列表的交集。 下面是一個示例:

listed = [(1, 1), (1, 2), (1, 3), (1, 4)]
listed1=[(1, 1), (2, 1), (3, 1)]
set(listed1)&set(listed)
>>>{(1, 1)}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM