Task
Inputs
Lists of products stored in a CSV file, where each line represents the shopping list of a single client:
Outputs
A CSV file:
- Header: products names sorted by number of appearances in the input file.
- For each line
k
we output boolean vectors where each of its elements indicates whether thei
-th product was present on the linek
in the input file or not.
Approach 1
from collections import defaultdict
with open('bigtest.csv', 'r') as inp:
index = defaultdict(lambda: set())
for line_number, line_str in enumerate(inp):
products = line_str[:-1].split(',')
for product in products:
index[product].add(line_number)
product_names = index.iterkeys()
sorting_key = lambda name: len(index[name])
header = sorted(product_names, key=sorting_key, reverse=True)
def generate_table():
for line in range(line_number + 1):
yield (1 if line in index[product] else 0 for product in header)
with open('formal0.csv', 'w') as out:
print >> out, ','.join(header)
for vector in generate_table():
print >> out, ','.join(str(val) for val in vector)
Approach 2
More declarative
from collections import defaultdict
with open('bigtest.csv', 'r') as inp:
data = (line[:-1].split(',') for line in inp)
index = defaultdict(lambda: set())
for line_number, products in enumerate(data):
for product in products:
index[product].add(line_number)
header = sorted(
index.iterkeys(),
key=lambda p: len(index[p]),
reverse=True
)
table = ((1 if line in index[product] else 0 for product in header)
for line in range(line_number + 1))
with open('formal0.csv', 'w') as out:
print >> out, ','.join(header) + '\n' + '\n'.join(','.join(map(str, vector))
for vector in table)
Concerns
- Readability
- Clean way to make nested generators?
- Am I abusing
.join()
? - How much declarative style is too much?
formal0.csv
, why is this? Do you perform any operations on this data before and after? \$\endgroup\$