各列の値が数値または文字列になるようにフォーマットされたテキスト ファイルを Python で読み込んでいます。
これらの値が文字列の場合、その文字列の一意の ID を割り当てる必要があります (同じ列の下のすべての文字列で一意です。同じ列の下に同じ文字列が表示される場合は、同じ ID を割り当てる必要があります)。
それを行うための効率的な方法は何ですか?
新しい ID を生成するデフォルト値ファクトリで defaultdict を使用します。
ids = collections.defaultdict(itertools.count().next)
ids['a'] # 0
ids['b'] # 1
ids['a'] # 0
defaultdict でキーを検索するときに、まだ存在しない場合、defaultdict はユーザー提供のデフォルト値ファクトリを呼び出して値を取得し、それを返す前に格納します。
collections.count()
0 からカウントアップする反復子を作成するため、collections.count().next
呼び出されるたびに新しい整数を生成するバインドされたメソッドです。
これらのツールを組み合わせると、以前に検索したことがないものを検索するたびに、新しい整数を返す dict が生成されます。
defaultdict の回答が python 3 用に更新されました。.next
現在.__next__
は であり、「魔法の」__*__
メソッドの使用が推奨されていない pylint コンプライアンス用です。
ids = collections.defaultdict(functoools.partial(next, itertools.count()))
セットを作成し、文字列をセットに追加します。これにより、文字列が重複しないことが保証されます。enumerate を使用して、各文字列の一意の ID を取得できます。ファイルを再度書き出すときに、この ID を使用します。
ここでは、2 番目の列がテキストまたは整数をスキャンする列であると想定しています。
seen = set()
with open('somefile.txt') as f:
reader = csv.reader(f, delimiter=',')
for row in reader:
try:
int(row[1])
except ValueError:
seen.add(row[1]) # adds string to set
# print the unique ids for each string
for id,text in enumerate(seen):
print("{}: {}".format(id, text))
これで、同じロジックを使用して、ファイルの各列に複製できます。事前に列の長さがわかっている場合は、セットのリストを作成できます。ファイルに 3 つの列があるとします。
unique_strings = [set(), set(), set()]
with open('file.txt') as f:
reader = csv.reader(f, delimiter=',')
for row in reader:
for column,value in enumerate(row):
try:
int(value)
except ValueError:
# It is not an integer, so it must be
# a string
unique_strings[column].add(value)