2016-03-08 13 views
5

Birden çok işlevi uygulamak istediğim 2B veriye sahibim. Gerçek kod xlrd ve bir .xlsx dosyasını kullanır, ancak aşağıdaki kazan-plakasını sağlayacağım, böylece çıktı çoğaltılabilir. data (giriş biçimi başına) dizeleri bir 2D dizi içerir, bu nesnedeHarita ile birden çok işlevi uygulama

fake_data = '''a, b, c, 
       1, 2, 3, 4 
       e, f, g, 
       5, 6, i, 
       , 6, , 
       , , , ''' 

sheet = Sheet(fake_data) 

ve ben bu nesnenin sütunlarda işlemleri gerçekleştirmek istiyorum:

class Data: 
    def __init__(self, value): 
     self.value = value 

class Sheet: 
    def __init__(self, data): 
     self.data = [[Data(value) for value in row.split(',')] for row in data.split('\n')] 
     self.ncols = max(len(row) for row in self.data) 

    def col(self, index): 
     return [row[index] for row in self.data] 

bir Sheet oluşturuluyor. Bu noktaya kadar hiçbir şey benim kontrolümde değil.

bu yapıya üç şey yapmak istiyorum: sütunlara satırları devrik her Data nesneden value ayıklamak ve float değerlere dönüştürmek için deneyin. Değer float değilse, soyulmuş beyaz boşluklu bir str dönüştürülmelidir.

from operators import attrgetter 

# helper function 
def parse_value(value): 
    try: 
     return float(value) 
    except ValueError: 
     return str(value).strip() 

# transpose 
raw_cols = map(sheet.col, range(sheet.ncols)) 

# extract values 
value_cols = (map(attrgetter('value'), col) for col in raw_cols) 

# convert values 
typed_cols = (map(parse_value, col) for col in value_cols) 

# ['a', 1.0, 'e', 5.0, '', ''] 
# ['b', 2.0, 'f', 6.0, 6.0, ''] 
# ['c', 3.0, 'g', 'i', '', ''] 
# ['', 4.0, '', '', '', ''] 

O map iki kez her sütun uygulanır görülebilir. Diğer durumlarda, her sütuna ikiden fazla bir işlev uygulamak istiyorum.

Birden çok işlevi yinelenen girişlerle eşlemek için daha iyi bir yol var mı? Daha da fazlası, jeneratörün anlaşılmasını önlemek ve eşleştirmeyi her bir iç-yinelemeye doğrudan uygulamak için var mıdır? Ya da, hep birlikte bu yaklaşım için daha iyi ve genişletilebilir bir yol var mı?

Bu sorunun xlrd'a özgü olmadığını unutmayın, yalnızca geçerli kullanım vakasıdır.

+0

hatırlatma: 'harita (f, harita (g, xs)) '' (xs oluşturmak (f, g)) harita 'aynı çıkışı vardır; Eski koleksiyonda iki kez yinelenecek, ancak ikincisi sadece bir kez yinelenecek. – naomik

+0

@naomik Right, keşke sanırım bir "compose" var sanırım. –

+1

Jared, kolayca kendi yapabilirsiniz. “besle”, lambda f, g: lamda x: f (g (x)) 'dan başka bir şey değildir. Ya da sadece 'map (lambda x: f (g (x)), xs)' – naomik

cevap

2

En basit çözüm, birden fazla işlevi aynı yinelenebilirliğe uygulayacak kendi işlevinizi yuvarlamaktır. Burada

def map_many(iterable, function, *other): 
    if other: 
     return map_many(map(function, iterable), *other) 
    return map(function, iterable) 

olumsuz kullanımı map(function, iterable) den tersine döner ve tekrar (Python 3.X içinde olabildiğince gibi) argüman kabul map uzatmak için garip olurdu olmasıdır.

Kullanım:

map_many([0, 1, 2, 3, 4], str, lambda s: s + '0', int) 
# [0, 10, 20, 30, 40] 
4

Kolayca kulüp lambda,

typed_cols = (map(lambda element:parse_value(element['value']), col) 
       for col in value_cols) 

kullanarak son iki map aramaları Sheet.col içine ayıklanması, IMO kodun okunabilirliği benzer ayrıştırma sopayı ve etkileyecek olabilir çıkarabilirler.

İlgili konular