開発環境
Windows 10
Python 3.7.3
※ pandasモジュール使用
開発/投稿の動機
コマンドの出力結果をパースして分析するために開発、メモを兼ねて投稿
変換対象文字列
sample_output.py
output = '''aaa
bbb
ccc
ddd
eee
fff
gggg
hhh
iii
jjj'''
データ構造に関する変数を定義
setting.py
# インデント単位を定義
indent_num = 4
# 階層数を定義
max_depth = int(max([i.count(' ') for i in output_list]) / indent_num)
StringからDataFrameへ加工
str_to_df.py
import pandas as pd
output_df = pd.DataFrame(index=[],columns=range(max_depth + 1))
for i in range(len(output_list)):
if output_list[i].count(' ') == 0:
# 最深までの足りない要素をNone埋めして挿入
temp_row = [output_list[i]]
temp_row.extend([None] * (max_depth)) # max_depth - すでに挿入した要素数(1) + depthが0から始まるため1を足す をプラスマイマスゼロのため省略
output_df = output_df.append(pd.Series(temp_row, index=output_df.columns), ignore_index=True)
outer_row = [output_list[i]]
depth = 0
else:
# 1つ前のレコードよりも1階層深かったら"depth"を進める
if output_list[i].count(' ') == (depth + 1) * indent_num:
depth += 1
# 挿入用のリストを作成
temp_row = outer_row.copy()
temp_row.append(output_list[i].strip(' '))
list_length = len(temp_row)
# 最深よりも浅いレコードはNone埋めして挿入
if list_length < max_depth + 1:
temp_row.extend([None] * (max_depth - list_length + 1))
output_df = output_df.append(pd.Series(temp_row, index=output_df.columns), ignore_index=True)
# 最深のレコードはそのまま挿入
else:
output_df = output_df.append(pd.Series(temp_row, index=output_df.columns), ignore_index=True)
# 次のレコードが1階層深かったらouter_rowを挿入したレコード(Noneは除去)と置き換える
if i + 1 < len(output_list):
if output_list[i + 1].count(' ') == (depth + 1) * indent_num:
outer_row = [x for x in temp_row if x]
DataFrameからDictionaryへ加工
df_to_dict.py
output_dict = {}
for i in sorted(output_df.keys())[:-1]:
for j in [x for x in output_df[i].drop_duplicates() if x]:
if i == 0:
# 配下の要素が無かったら外側の辞書定義のみ
if len([x for x in output_df[output_df[i] == j][i + 1] if x]) == 0:
output_dict[j] = None
else:
output_dict[j] = {}
filtered_dict = output_dict[j]
else:
# 配下の要素が無かったら自分だけ追加
if len([x for x in output_df[output_df[i] == j][i + 1] if x]) == 0:
if (j not in filtered_dict) & (i != max_depth - 1):
filtered_dict[j] = None
# 配下の要素があったら辞書を作って埋める
elif i != max_depth - 1:
filtered_dict[j] = {}
temp_dict = {}
# 配下のキーをループ処理
for key in [x for x in output_df[output_df[i] == j][i + 1].drop_duplicates() if x]:
# すでにキーがあったら更新
if key in temp_dict.keys():
temp_dict.update({key:[x for x in list(output_df[output_df[max_depth - 1] == key][max_depth]) if x]})
# 無かったら追加
else:
temp_dict[key] = [x for x in list(output_df[output_df[max_depth - 1] == key][max_depth]) if x]
# 作成した辞書を挿入
filtered_dict[j] = temp_dict
あとがき
求める出力を得られるようになったため当面このまま使うが、不要なロジックの精査を要する。