2011-08-08 5 views
2

나는 이름이 붙여진 튜플의 2 차원리스트를 가지고있다. (각각의 튜플에 N 개의 값이 있다고 가정하자.) 각각을 풀린 N 개의 다른 2 차원리스트로 풀고 싶다. -D list는 원래 목록의 단일 속성으로 완전히 구성됩니다.파이썬은 명명 된 튜플의 2 차원리스트를 풀다. ​​

[[0, 1, 2], 
[3, 4, 5], 
[6, 7, 8]] 

[[0.0, 1.0, 2.0], 
[3.0, 4.0, 5.0], 
[6.0, 7.0, 8.0]] 

[['0', '1', '2'], 
['3', '4', '5'], 
['6', '7', '8']] 

난 그냥 튜플의 1 차원 목록이 있다면 내가 사용하는 것 :

>>> combo = namedtuple('combo', 'i, f, s') 
>>> combo_mat = [[combo(i + 3*j, float(i + 3*j), str(i + 3*j)) for i in range(3)] 
       for j in range(3)] 
>>> combo_mat 
[[combo(i=0, f=0.0, s='0'), combo(i=1, f=1.0, s='1'), combo(i=2, f=2.0, s='2')], 
[combo(i=3, f=3.0, s='3'), combo(i=4, f=4.0, s='4'), combo(i=5, f=5.0, s='5')], 
[combo(i=6, f=6.0, s='6'), combo(i=7, f=7.0, s='7'), combo(i=8, f=8.0, s='8')]] 

나는 3 개 결과 싶습니다 예를 들어 나는이 2-D 목록이있는 경우 같은 zip(*mylist) :

>>> zip(*[combo(i=0, f=0.0, s='0'), combo(i=1, f=1.0, s='1'), combo(i=2, f=2.0, s='2')]) 
[(0, 1, 2), (0.0, 1.0, 2.0), ('0', '1', '2')] 

그리고 난 그냥 중첩에 의해 내 상황이를 확장 할 수

>>> zip(*[zip(*combs) for combs in combo_mat]) 
[((0, 1, 2), 
    (3, 4, 5), 
    (6, 7, 8)), 
((0.0, 1.0, 2.0), 
    (3.0, 4.0, 5.0), 
    (6.0, 7.0, 8.0)), 
(('0', '1', '2'), 
    ('3', '4', '5'), 
    ('6', '7', '8'))] 

그러나 이것은 내가 원하는 목록을 제공하지 않으며 중첩 된 풀기 zip(*) 함수는 읽을 수 없습니다. 누구든지 더 pythonic 솔루션에 대한 아이디어가 있습니까? 최종 결과의 어딘가에서 튜플 속성의 이름을 사용할 수 있다면 보너스 포인트가됩니다. 내가 좋아하는 각각의 행렬에 튜플의 속성의 이름을 매핑 DICT 가질 수 있다면

사실

, 지금은 그것을 생각, 그것은 이상적인이 될 것입니다 :

{'i': [[0, 1, 2], 
     [3, 4, 5], 
     [6, 7, 8]], 
'f': [[0.0, 1.0, 2.0], 
     [3.0, 4.0, 5.0], 
     [6.0, 7.0, 8.0]] 
's': [['0', '1', '2'], 
     ['3', '4', '5'], 
     ['6', '7', '8']]} 

답변

3

기능 프로그래밍을 http://www.astro.ufl.edu/~warner/prog/python.html (단어 "트랜스"에 대한 검색)? 그것은 본질적으로 중첩 참아의 깨끗한 버전입니다 :

def fmap_element(f, el): 
    return f(el) 

def fmap_list(f, l): 
    return [fmap_element(f, el) for el in l)] 

def fmap_lol(f, lol): 
    return [fmap_list(f,l) for l in lol] 

def split_nt_lol(nt_lol): 
    return dict((name, fmap_lol(lambda nt: getattr(nt, name), nt_lol)) 
       for name in nt_lol[0][0]._fields) 

사용법 :

>>> split_nt_lol(combo_mat) 
{'i': [[0, 1, 2], [3, 4, 5], [6, 7, 8]], 
's': [['0', '1', '2'], ['3', '4', '5'], ['6', '7', '8']], 
'f': [[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]]} 
+0

우수, 개인 변수'_fields'를 열거하지 않고'getattr()'을 사용하는 것을 좋아합니다. 그것은 더 깨끗해 보인다. –

+0

나는 원래 광산에서'getattr'을 사용했지만'getattr'처럼 깨끗하지 못하다고 느꼈습니다.:-) – kindall

+0

나는 아직도'_fields'를 사용합니다. 그것없이 명명 된 튜플의 필드 이름 목록을 얻는 방법이 있는지 확실하지 않다. – Claudiu

0

를이 될 수 있습니다 단순히 transpose()를 사용하여 배열을 transpose함으로써 얻을 수 있습니다.

참조 : 구조에

+0

음, 전혀 모르겠습니다. 무슨 뜻인지 설명해 주시겠습니까? –

2
matrices = {} 

for num, name in enumerate(combo._fields): 
    matrix = [] 
    for i in combo_mat: 
     row = [] 
     for j in i: 
      row.append(j[num]) 
     matrix.append(row) 
    matrices[name] = matrix 
+0

아하 좋은데, namedtuples에'_fields' 속성이 있다는 것을 몰랐습니다. –

+0

그러나 속성 이름, 값 쌍에 액세스하는 더 직접적인 방법이 있습니까? 어쩌면 사전에 저장해야 할 것입니다. –

+0

아 예, 광산보다 더 평범한 .. – Claudiu

1

이 중첩 zip(*) 기능보다 더 읽을 수없는,하지만이 작업을 수행합니다

>>> dict((key, [[c._asdict()[key] for c in combos] for combos in combo_mat]) 
     for key in ['i', 'f', 's']) 
{'i': [[0, 1, 2], [3, 4, 5], [6, 7, 8]], 
's': [['0', '1', '2'], ['3', '4', '5'], ['6', '7', '8']], 
'f': [[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]]} 

다음과 같이 읽기 쉽게 만들 수 있다고 가정합니다.

def get_mat(combo_mat, key): 
    return [[c._asdict()[key] for c in combos] for combos in combo_mat] 

def get_mat_dict(combo_mat, keys): 
    return dict((key, get_mat(combo_mat, key)) for key in keys) 
+0

흠 나는 그것을 좋아하지만, 당신은 그것이 특별히 읽을 수있는 것이 아니라고 옳다. –

+0

우수한 개정판, 가능하면 +1 할 수 있습니다. –