次の関数を返すことについて質問があります。次のような食品リストを含むファイルが与えられます。
'''
bread
bun
milk
soya milk
'''
そして、食品のリストのリストを返さなければなりません。[['bread','bun'], ['milk','soya milk']]
私はPythonとプログラミングに非常に慣れていないため、リストを作成するためにforループに固執しています。どんな入力でも大歓迎です-kev
それは動作します...
grocery_list_file = open('foods.txt','r').read()
foods = grocery_list_file.split("\n\n") #split on blank lines
result = []
for food in foods:
newFood = food.split("\n") # split the lines, creating the output...
result += [newFood]
return result
一行で:
print [f.strip().split("\n") for f in open('foods.txt','r').read().split("\n\n")]
新しいカテゴリに到達したときにサブリストを追加してから、新しいsub_listを開始します。ファイルの最後に到達したら、残りのsub_listを最後に追加することが重要です。
new_list.append("\n") #to make sure it appends the last category
for next_food in new_list:
if next_food = "\n":
result.append(sub_list)
sub_list = []
else:
sub_list.append(next_food)
入力ファイルが完全にメモリに読み込まれるほど小さい場合は、次のようにします。
with open('grocery_list.txt', 'rt') as grocery_list_file:
data = grocery_list_file.read()
sublist = [item.strip().split('\n') for item in data.split('\n\n')]
出力:
sublist: [['bread', 'bun'], ['milk', 'soya milk']]
かなり近いです。を使用する代わりにwhile len(next_food) > 0:
、 if を使用して、 next_food が空白で空白でない場合の両方のケースを処理する必要があります。コメントが示すように、戻る直前に最後のサブリストを含める必要があります。
もう 1 つ確認すべきことは、next_food の末尾に改行が含まれているかどうかです。改行がある場合は削除する必要があります。最後に、 のチェックに代わるショートカットがありif len(next_food):
ます。単に書くだけで十分if next_food:
です。
これはあまり良い解決策ではありません...しかし、いくつかの楽しいトリック..
>>> s = '''
... bread
... bun
...
... milk
... soya milk
... '''
>>> import re
>>> parts = re.sub("[\[\]']","",str(s.strip().splitlines())).split(", ,")
>>> import string
>>> print [map(string.strip,p.split(",")) for p in parts]
[['bread', 'bun'], ['milk', 'soya milk']]
from itertools import groupby
def build_grocery_list():
# using "with" to open the file - recommended way
with open("foods.txt") as f:
# lines will contain all the lines in the file, without "\n" characters
lines = f.read().splitlines()
# initialize result as an empty list
result = []
# Now for the fun part: group file lines basing on whether they are empty
# (bool(string) is analogous to as using "if string:" -- will be True if
# the string is not empty)
#
# groupby works in such a way that it appends stuff to the group as long
# as "key" condition is the same, returning (key, group) pairs.
#
# So, we get pairs: (bool(string), string-group) where:
# - bool(string) is the group "key", delimiting empty and non-empty
# strings
# - string-group is a lazy *generator*, hence the "list(group)"
for nonblank, group in groupby(lines, bool):
if nonblank:
result.append(list(group))
return result
Python を学習している場合は、優れたitertoolsモジュールに慣れることを強くお勧めします。これは非常に便利です。
最も簡単でかなり読みやすい方法は次のとおりです。
>>> [el.strip().split('\n') for el in text.split('\n\n')]
[['bread', 'bun'], ['milk', 'soya milk']]
行に分割する\n\n
と、すぐに空白行が続きます
は先頭と末尾の.strip()
改行を削除するため、要素間の改行のみが存在します
その後split
、それらの要素がリストに分割され、リストのリストが生成されます
または、次を使用できますitertools.groupby
。
>>> [groups for groups in (list(g) for k, g in groupby(text.splitlines(), bool)) if groups[0]]
[['bread', 'bun'], ['milk', 'soya milk']]