如果在该元素中找到某个char,则返回列表元素的Pythonic方法

时间:2015-09-06 12:37:45

标签: python

我有一个问题。我正在编写一个数独求解器,例如对于正方形A1我想找到子网格中的9个相邻正方形的列表(A1,A2,A3,B1,B2,B3,C1,C2,C3)

我的计划是在A和1中拆分A1,然后返回'ABC'和'123'的叉积,但如果square [0] ='A,我无法弄清楚如何优雅地返回'ABC' ”。

我想找到一种优雅的方法来从一组列表中返回找到该元素的列表。 ['ABC','DEF','GHI'],当我输入A时,我想得到字符串'ABC'。

完整代码atm:

def cross_product(A, B):
    """Returns a list of the cross product of A and B."""
    return [a+b for a in A for b in B]

rows    = 'ABCDEFGHI'
cols    = '123456789'
squares = cross_product(rows, cols) # List of 81 squares

def find_row(square):
    """
    Returns list of strings with corresponding row values.
    Example: find_row('A2') -> ['A1','A2', ..., 'A9'] 
    """
    return cross_product(square[0], cols)

def find_col(square):
    """
    Returns list of strings with corresponding col values.
    Example: find_col('A2') -> ['A2','B2', ..., 'I2']
    """
    return cross_product(rows, square[1])

 def find_peers(square):
    """
    Returns list of strings of shared squares in the unit.
    Example: find_peers('A2') -> ['A1', 'A2', 'A3', 'B1' , ..., 'C3']
    """
    for e in ['ABC','DEF','GHI']:
        if square[0] in e:
            r = e

    for e in ['123','456','789']:
        if square[1] in e:
            c = e

    return cross_product(r, c)

有没有办法让find_peers(square)更加pythonic?

2 个答案:

答案 0 :(得分:2)

如果您正在对测试列表进行硬编码,则可以使用字典:

square_letter = {c: e for e in ['ABC','DEF','GHI'] for c in e}
square_number = {n: e for e in ['123','456','789'] for n in e}
r, c = square_letter[square[0]], square_number[square[1]]

square_lettersquare_number词典只需要生成一次。使用字典然后给你一个O(1)(恒定时间)查找。

如果这对性能至关重要,您可以通过函数的默认参数将映射绑定为本地:

square_letter = {c: e for e in ['ABC','DEF','GHI'] for c in e}
square_number = {n: e for e in ['123','456','789'] for n in e}
def find_peers(square, _letter=square_letter, _number=square_number):
    """
    Returns list of strings of shared squares in the unit.
    Example: find_peers('A2') -> ['A1', 'A2', 'A3', 'B1' , ..., 'C3']
    """
    return cross_product(_letter[square[0]], _number[square[1]])

演示:

>>> def cross_product(A, B):
...     """Returns a list of the cross product of A and B."""
...     return [a+b for a in A for b in B]
... 
>>> square_letter = {c: e for e in ['ABC','DEF','GHI'] for c in e}
>>> square_number = {n: e for e in ['123','456','789'] for n in e}
>>> def find_peers(square, _letter=square_letter, _number=square_number):
...     """
...     Returns list of strings of shared squares in the unit.
...     Example: find_peers('A2') -> ['A1', 'A2', 'A3', 'B1' , ..., 'C3']
...     """
...     return cross_product(_letter[square[0]], _number[square[1]])
... 
>>> find_peers('A2')
['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']
>>> find_peers('E8')
['D7', 'D8', 'D9', 'E7', 'E8', 'E9', 'F7', 'F8', 'F9']

答案 1 :(得分:2)

另一种解决方案,不使用dict:

from itertools import product

rows = list('ABCDEFGHI')
cols = list('123456789')
square_width = 3

def find_peers(cell):
    row, column = cell
    row_idx = rows.index(row)
    column_idx = cols.index(column)

    first_row = row_idx - row_idx % square_width
    first_column = column_idx - column_idx % square_width

    rows_range = rows[first_row:first_row + square_width]
    columns_range = cols[first_column:first_column + square_width]

    return [
        row + column for row, column in product(rows_range, columns_range)
    ]

>>> find_peers('A1')
['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']

>>> find_peers('D1')
['D1', 'D2', 'D3', 'E1', 'E2', 'E3', 'F1', 'F2', 'F3']

>>> find_peers('G1')
['G1', 'G2', 'G3', 'H1', 'H2', 'H3', 'I1', 'I2', 'I3']

>>> find_peers('G4')
['G4', 'G5', 'G6', 'H4', 'H5', 'H6', 'I4', 'I5', 'I6']