Apply multiple functions using a map

I have 2D data that I want to apply several functions to. The actual code uses xlrd and .xlsx file, but I provided the following boiler plate, to the solution was easily reproduced.

 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] 

Create sheet:

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

In this object, data contains a 2D array of strings (for input format), and I want to perform operations on the columns of this object. Nothing is controlled by me until this moment.

I want to do three things in this structure: wrap rows in columns, extract value from each data object, and try to convert the value to float . If the value is not equal to float , it should be converted to str with white space selected.

 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, '', '', '', ''] 

You can see that map is applied to each column twice. In other cases, I want to apply the function to each column more than two times.

Is there a better way to map multiple functions to iteration elements? Moreover, is it possible to avoid understanding the generator and directly apply the mapping to each iterable internal? Or is there a better and extensible way to get closer to this all together?

Please note that this question does not apply to xlrd , this is just the current use case.

+5
source share
2 answers

It seems like the easiest solution is to collapse your own function, which will apply multiple functions to one exterminated.

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

The downside here is that usage is canceled with map(function, iterable) , and it would be inconvenient to extend the map to accept arguments (as it could be in Python 3.X).

Using:

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

You can easily connect the last two map calls with lambda ,

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

While you can use a similar wand when parsing and extracting inside Sheet.col , IMO, which will affect the readability of the code.

+4
source

Source: https://habr.com/ru/post/1244628/


All Articles