0

リストのリストを受け取り、文字列を返す関数を見つけました。しかし、私はそれが何をしているのか正確に理解するのに苦労していますか? 以下のコードにコメントしてください。

def getAsTable(self, arrays):
    """ This method takes an array of arrays and returns string (which is really a table) 
    :param arrays: An array of arrays 
    :returns: string (this is really a table of the input)

    >>> [[a, b, b], [1, 2, 3], [4, 5, 6]]
    >>> a    b    c
    >>> 1    2    3
    >>> 4    5    6

    """
    def areAllEqual(lst):
        return not lst or [lst[0]] * len(lst) == lst

    if not areAllEqual(map(len, arrays)):
        return "Cannot print a table with unequal array lengths"

    verticalMaxLengths = [max(value) for value in map(lambda * x:x, *[map(len, a) for a in arrays])]
    spacedLines = []

    for array in arrays:
        spacedLine = ''
        for i, field in enumerate(array):
            diff = verticalMaxLengths[i] - len(field)
            spacedLine += field + ' ' * diff + '\t'
        spacedLines.append(spacedLine)

    return '\n  '.join(spacedLines)
4

1 に答える 1

2

簡単な説明によりmap、以下のコードにコメントを散らかさなくても済みます。

このmap関数は、最初の引数 (通常は関数ですが、クラスまたはその他の呼び出し可能なものでもかまいません) を 2 番目の引数の各値に適用し、結果のリストを返します。与えられた関数で各要素を変換すると考えてください。2 つの引数で使用すると、次のように機能します。

def map(fct, iterable): return [fct(x) for x in iterable]

3 つ以上の引数とともに使用するとmap、最初の引数の後のすべての引数が iterable であると見なされ、それらを並列に反復処理し、n 番目のパスで各 iterable の n 番目の要素を関数に渡します。

def p(a,b,c): print "a: %s, b:%s, c:%s"
map(p, "abc", "123", "456") #-> prints "a 1 4", then "b 2 5", then "c 3 6"

コードのコメント付きバージョン:

def getAsTable(self, arrays):

    #helper function checking that all values contained in lst are equal
    def areAllEqual(lst):
        #return true for the empty list, or if a list of len times the first
        #element equals the original list
        return not lst or [lst[0]] * len(lst) == lst

    #check that the length of all lists contained in arrays is equal
    if not areAllEqual(map(len, arrays)):
        #return an error message if this is not the case
        #this should probably throw an exception instead...
        return "Cannot print a table with unequal array lengths"

    verticalMaxLengths = [max(value) for value in map(lambda * x:x, *[map(len, a) for a in arrays])]

この行をいくつかの部分に分けてみましょう:

(1) [map(len, a) for a in arrays]

これは、配列内のすべてのリストに len をマップします。つまり、要素の長さのリストのリストを取得します。例として、入力[["a","b","c"], ["1","11","111"], ["n", "n^2", "n^10"]]の場合、結果は になります[[1, 1, 1], [1, 2, 3], [1, 2, 4]]

(2) map(lambda *x:x, *(1))

は、(1) で取得したリストをアンラップします。*つまり、各要素が個別の引数としてマップに渡されます。上記のように、複数の引数を指定すると、map は a を関数に渡します。ここで定義されたラムダは、すべての引数をタプルとして返すだけです。上記の例を続けると、入力[[1, 1, 1], [1, 2, 3], [1, 2, 4]] の場合、結果は[(1, 1, 1), (1, 2, 2), (1, 3, 4)] 基本的に入力の行列転置になります

(3) [max(value) for value in (2)]

これは、(2) で返されたリストのすべての要素に対して max を呼び出します (要素がタプルであることに注意してください)。入力[(1, 1, 1), (1, 2, 2), (1, 3, 4)]の場合、結果は になります[1, 2, 4]

したがって、ここでのコンテキストでは、行全体が入力配列を受け取り、各列の要素の最大長を計算します。

コードの残りの部分:

    #initialize an empty list for the result
    spacedLines = []

    #iterate over all lists
    for array in arrays:
        #initialize the line as an empty string
        spacedLine = ''
        #iterate over the array - enumerate returns position (i) and value
        for i, field in enumerate(array):
            #calculate the difference of the values length to the max length
            #of all elements in the column
            diff = verticalMaxLengths[i] - len(field)
            #append the value, padded with diff times space to reach the
            #max length, and a tab afterwards
            spacedLine += field + ' ' * diff + '\t'
        #append the line to the list of lines
        spacedLines.append(spacedLine)

    #join the list of lines with a newline and return
    return '\n  '.join(spacedLines)
于 2012-11-14T09:58:18.327 に答える