

2次元配列liがあり

[code]

    li=[[0,0,0],
        [0,2,0],
        [0,1,0],
        [0,0,0],
        [0,3,0],
        [0,0,0]]
    
[/code]

2次元配列liの中央の列の数字(0,2,1,0,3,0)に、  
(質問1)１つでも0より上の数字がある場合の判定、  
(質問2)すべて0の判定、  
をif文で行いたいです。

(質問3)また、中央の列の数字で、0より上の数字が最後は何行目に出現したか(今回の場合は3が出現した5番目)も知りたいです。

よろしくお願いします。


CC BY-SA 3.0
2015-11-19T03:56:28.733
19016
2015-11-19T15:54:49.760
2015-11-19T06:53:58.110
3054
13312
question
python
pythonで2次元配列を用いた条件分岐について


回答A

[code]

    >>> # 質問1
    >>> any_positive = False
    >>> for x in li:
    ...     if x[1] > 0:
    ...         any_positive = True
    ...         break
    ... 
    >>> any_positive
    True
    
    >>> # 質問2
    >>> all_zero = True
    >>> for x in li:
    ...     if x[1] != 0:
    ...         all_zero = False
    ...         break
    ... 
    >>> all_zero
    False
    
    >>> # 質問3
    >>> last_positive = None
    >>> for idx, x in enumerate(li):
    ...     if x[1] > 0:
    ...         last_positive = idx
    ... 
    >>> last_positive
    4
    
[/code]

回答B

[code]

    >>> # 質問1
    >>> any(x[1] > 0 for x in li)
    True
    
    >>> # 質問2
    >>> all(x[1] == 0 for x in li)
    False
    
    >>> # 質問3
    >>> [i for i, x in enumerate(li) if x[1] > 0][-1]
    4
    
[/code]


CC BY-SA 3.0
2015-11-19T04:52:15.470
19019
2015-11-19T04:57:43.620
2015-11-19T04:57:43.620
806
806
19016
answer


全ての判定を一度に行ないたいのだと解釈しました。  
「中央の列」は「行」の2番目の要素(インデックスでは1)の事だとします。

「最後は何行目に出現したか」だけ分かればよいので、リストは末尾から見ていっています。  
見つかったら、そこでループを抜けます。  
リストのインデックスは0から始まるので、行数の表示にはインデックスに1足しています。

[code]

    found_target = False
    for i in range(len(li)-1, -1, -1):
        if li[i][1] > 0:
            print("最後尾ターゲットは", li[i][1], "で、", i+1, "行目")
            found_target = True
            break
    if not found_target:
        print("ターゲットなし")
    
[/code]

イテレータ版

[code]

    import itertools as it
    target = list(it.islice(((i, v[1]) for i,v in enumerate(reversed(li)) if v[1]>0), 1))
    if target:
        print("最後尾ターゲットは", target[0][1], "で、", len(li)-target[0][0], "行目")
    else:
        print("ターゲットなし")
    
[/code]


CC BY-SA 3.0
2015-11-19T07:06:45.220
19030
2015-11-19T07:06:45.220
3054
19016
answer


(質問1)１つでも0より上の数字がある場合の判定

[code]

    print sum(zip(*li)[1]) > 0
    
[/code]

(質問2)すべて0の判定

[code]

    print sum(zip(*li)[1]) == 0
    
[/code]

(質問3)また、中央の列の数字で、0より上の数字が最後は何行目に出現したか

[code]

    for i, e in reversed(list(enumerate(zip(*li)[1]))):
        if e > 0:
            print i+1, e
            break
    else:
        print "not found"
    
[/code]

質問3はもっといい答えがあると思います。

EDIT: 他の方の回答から得たヒントを組み合わせ。

[code]

    center = zip(*li)[1]
    # Q1
    print any(map(lambda x: x > 0, center))
    # Q2
    print all(map(lambda x: x == 0, center))
    
[/code]


CC BY-SA 3.0
2015-11-19T07:16:07.217
19032
2015-11-19T15:54:49.760
2015-11-19T15:54:49.760
7837
7837
19016
answer


numpy を使ってみます。

[code]

    import numpy as np
    
    li=[[0,0,0], [0,2,0], [0,1,0], [0,0,0], [0,3,0], [0,0,0]]
    x = np.array([tuple(l) for l in li],
                 dtype=[('l','int'), ('c','int'), ('r', 'int')])
    
    # 質問1
    any(x['c'] > 0)
    
    # 質問2
    all(x['c'] == 0)
    
    # 質問3
    np.where(x['c'] > 0)[0][-1]
    
[/code]


CC BY-SA 3.0
2015-11-19T08:26:56.463
19036
2015-11-19T08:26:56.463
19016
answer


なるべく基本的な関数を用いて書いてみました.  
質問３では見つからない場合-1を返します.  

[code]

    li=[[0,0,0],[0,2,0],[0,1,0],[0,0,0],[0,3,0],[0,0,0]]
    
    # 質問1
    print (reduce(lambda x,y: (y[1] > 0) or x,li,False))
    # 質問2
    print (reduce(lambda x,y: (y[1] > 0) and x,li,True))
    # 質問3
    print (reduce(lambda x,y: (lambda z : (x[0]+1,z)) (x[0] if y[1] > 0 else x[1]),li,(0,-1)))[1]
    
[/code]


CC BY-SA 3.0
2015-11-19T08:58:37.963
19038
2015-11-19T08:58:37.963
13199
19016
answer