映射的子排序列表
Subsorting list of mappings
我有如下映射
mapping = [
"key1",
"key2",
"key3",
"key4",
"key5#1",
"key5#4",
"key5#2",
"key5#3",
"key6#1",
"key6#2"
]
和列表列表,例如[['val1', 'val2', 'val3', 'val4', 'val5', 'val6', 'val7', 'val8', 'val9' 'val10']]
我想以字典列表结束,例如
[{
"key1": "val1",
"key2": "val2",
"key3": "val3",
"key4": "val4",
"key5": ["val5", "val7", "val8", "val6"],
"key6": ["val9", "val10"],
}]
这样每个没有 #
的键只有 1 个值,而带有 #
的键有一个有序列表,按 #
之后的整数排序。我现在拥有的是:
for i in range(len(mapping)):
if '#' in mapping[i]:
result.setdefault(mapping[i].split('#')[0], []).append(row[i])
else:
result[mapping[i]] = row[i]
但是,这不会根据 #
之后的数字对值进行排序。
你可以在这里使用itertools.groupby
。这个想法是使用映射中的键创建一个字典,最初每个键将被初始化为一个 None
的列表,其大小为一个键的重复次数。
from itertools import groupby
dct = {}
for k, g in groupby(mapping, lambda x: x.split('#')[0]):
length = sum(1 for _ in g)
dct[k] = [None] * length
...
现在 dct
看起来像:
>>> dct
{'key3': [None],
'key2': [None],
'key1': [None],
'key6': [None, None],
'key5': [None, None, None, None],
'key4': [None]}
请注意,如果映射尚未排序,那么我们可以使用 mapping.sort(key=lambda x: x.split('#')[0])
对其进行排序。这会将相似的键组合在一起。
上面的事情也可以通过首先识别每个键的计数然后使用计数初始化dict
来完成。这样可以在 O(N) 时间内完成,以防 mapping
中的相似键尚未分组。
>>> from collections import Counter
>>> dct = {k: [None] * v for k, v in Counter(
key.split('#')[0] for key in mapping).items()}
现在我们可以遍历映射和列表并相应地更新 dct
中的值:
for key, value in zip(mapping, lst[0]):
if '#' not in key:
dct[key] = value
else:
key, index = key.split('#')
# Simply assign the value to the index
dct[key][int(index)-1] = value
...
>>> dct
{'key3': 'val3',
'key2': 'val2',
'key1': 'val1',
'key6': ['val9', 'val10'],
'key5': ['val5', 'val7', 'val8', 'val6'],
'key4': 'val4'}
这是你要的吗?
for i, key in enumerate(mapping):
if '#' in key:
key, order = key.split('#')
result.setdefault(key, []).insert(int(order) - 1, row[i])
else:
result[key] = row[i]
备注:
- 使用
enumerate
- for i in range(len(something))
被认为是坏习惯
- 在 Python3 中需要将
order
转换为 int
- 插入采用 int,字符串无效。
听起来像是 groupby
和列表切片的工作。请注意,val9
.
后的 row
中缺少逗号
def split_key(k):
if '#' in k:
return k.split('#')[0]
else:
return k
def group_keys(keys):
for K, G in groupby(keys, key=split_key):
yield split_key(K), sum(1 for g in G)
def slice_row(mapping, row):
i = 0
for key, length in group_keys(mapping):
if length == 1:
yield key, row[i]
else:
yield key, row[i:i + length]
i += length
print(dict(slice_row(mapping, row[0])))
# >>> {'key4': 'val4', 'key6': ['val9', 'val10'], 'key5': ['val5', 'val6', 'val7', 'val8'], 'key3': 'val3', 'key1': 'val1', 'key2': 'val2'}
我有如下映射
mapping = [
"key1",
"key2",
"key3",
"key4",
"key5#1",
"key5#4",
"key5#2",
"key5#3",
"key6#1",
"key6#2"
]
和列表列表,例如[['val1', 'val2', 'val3', 'val4', 'val5', 'val6', 'val7', 'val8', 'val9' 'val10']]
我想以字典列表结束,例如
[{
"key1": "val1",
"key2": "val2",
"key3": "val3",
"key4": "val4",
"key5": ["val5", "val7", "val8", "val6"],
"key6": ["val9", "val10"],
}]
这样每个没有 #
的键只有 1 个值,而带有 #
的键有一个有序列表,按 #
之后的整数排序。我现在拥有的是:
for i in range(len(mapping)):
if '#' in mapping[i]:
result.setdefault(mapping[i].split('#')[0], []).append(row[i])
else:
result[mapping[i]] = row[i]
但是,这不会根据 #
之后的数字对值进行排序。
你可以在这里使用itertools.groupby
。这个想法是使用映射中的键创建一个字典,最初每个键将被初始化为一个 None
的列表,其大小为一个键的重复次数。
from itertools import groupby
dct = {}
for k, g in groupby(mapping, lambda x: x.split('#')[0]):
length = sum(1 for _ in g)
dct[k] = [None] * length
...
现在 dct
看起来像:
>>> dct
{'key3': [None],
'key2': [None],
'key1': [None],
'key6': [None, None],
'key5': [None, None, None, None],
'key4': [None]}
请注意,如果映射尚未排序,那么我们可以使用 mapping.sort(key=lambda x: x.split('#')[0])
对其进行排序。这会将相似的键组合在一起。
上面的事情也可以通过首先识别每个键的计数然后使用计数初始化dict
来完成。这样可以在 O(N) 时间内完成,以防 mapping
中的相似键尚未分组。
>>> from collections import Counter
>>> dct = {k: [None] * v for k, v in Counter(
key.split('#')[0] for key in mapping).items()}
现在我们可以遍历映射和列表并相应地更新 dct
中的值:
for key, value in zip(mapping, lst[0]):
if '#' not in key:
dct[key] = value
else:
key, index = key.split('#')
# Simply assign the value to the index
dct[key][int(index)-1] = value
...
>>> dct
{'key3': 'val3',
'key2': 'val2',
'key1': 'val1',
'key6': ['val9', 'val10'],
'key5': ['val5', 'val7', 'val8', 'val6'],
'key4': 'val4'}
这是你要的吗?
for i, key in enumerate(mapping):
if '#' in key:
key, order = key.split('#')
result.setdefault(key, []).insert(int(order) - 1, row[i])
else:
result[key] = row[i]
备注:
- 使用
enumerate
-for i in range(len(something))
被认为是坏习惯 - 在 Python3 中需要将
order
转换为int
- 插入采用 int,字符串无效。
听起来像是 groupby
和列表切片的工作。请注意,val9
.
row
中缺少逗号
def split_key(k):
if '#' in k:
return k.split('#')[0]
else:
return k
def group_keys(keys):
for K, G in groupby(keys, key=split_key):
yield split_key(K), sum(1 for g in G)
def slice_row(mapping, row):
i = 0
for key, length in group_keys(mapping):
if length == 1:
yield key, row[i]
else:
yield key, row[i:i + length]
i += length
print(dict(slice_row(mapping, row[0])))
# >>> {'key4': 'val4', 'key6': ['val9', 'val10'], 'key5': ['val5', 'val6', 'val7', 'val8'], 'key3': 'val3', 'key1': 'val1', 'key2': 'val2'}