转换为 dict/type 的列表,一个包含字符串列表的字符串列表?
Convert to list of dict/type, a list of strings containing lists of strings?
a = ['foo', 'bar', ['can', 'haz']]
希望对每对字符串应用一个函数,替换它们,包括列表中的字符串。例如,
f = lambda k,v: {'key': k, 'val': v}
这样 f(a)
就会变成:
[{'key': 'foo', 'val': 'bar'}, [{'key': 'can', 'val': 'haz'}]]
以上 a
只有 2 个维度,但我会对 k 个维度感兴趣。在发现用 dict
或其他 f
替换每个层次结构级别的所有非列表元素不是正确的用例之前,就开始与 boltons.iterutils.remap
一起破解某些东西……
编辑:另一个例子
# create some random variables, alternative: `locals().update({c: (round(…`
a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z = tuple(
(round(abs(random()) ** 10, 4)
if randint(0, 1) % 2 == 0
else randint(20, 50)
if randint(0, 1) % 2 == 0
else ('foo', 'bar', 'can', 'haz', 'bzr')[randint(0, 4)])
for c in ascii_lowercase)
l1 = [a, b, c, d, e, f, g, [h, i, j, k],
l, m, n, [o, p, q, r, [s, t, u, v, w, x, y, z], a, b], c, d, e]
g = lambda k,v: {'{}_key'.format(k): k, '{}_val'.format(k): v}
当有一对彼此相邻时,它应该对其应用类型构造函数 T,并直接连接(我有一个 add_to
支持字典、列表等的函数)任何前面的adjacent——没有列表 inbetwixt——否则原始标量应该以与之前相同的层次结构连接到列表中。这是 g(l1)
的预期输出,不包括变量评估:
[
{'a_key': a, 'a_val': b,
'c_key': c, 'c_val': d,
'e_key': e, 'e_val': f},
g,
[
{'h_key': h, 'h_val': i,
'j_key': j, 'j_val': k}
],
{'l_key': l, 'l_val': m},
n,
[
{'o_key': o, 'o_val': p,
'q_key': q, 'q_val': r},
[
{'s_key': s, 's_val': t,
'u_key': u, 'u_val': v,
'w_key': w, 'w_val': x,
'y_key': y, 'y_val': z}
],
{'a_key': a, 'a_val': b}
],
{'c_key': c, 'c_val': d},
e
]
您将需要递归以支持未定义数量的级别。
假设您的级别在每个级别的列表中始终有 2 或 3 个项目,则递归函数可能如下所示:
a = ['foo', 'bar', ['can', 'haz']]
def f(a):
k,v,b,*_ = a+[None]
result = [{"key":k,"val":v}]
if b: result.append(f(b))
return result
输出:
print(f(a))
# [{'key': 'foo', 'val': 'bar'}, [{'key': 'can', 'val': 'haz'}]]
b = ['foo', 'bar', ['can', 'haz', ['boo','yah',['dino','dog']]]]
print(f(b))
[
{'key': 'foo', 'val': 'bar'},
[
{'key': 'can', 'val': 'haz'},
[
{'key': 'boo', 'val': 'yah'},
[
{'key': 'dino', 'val': 'dog'}
]
]
]
]
假设每个列表的连续内容总是键值对或列表:
a = ['foo', 'bar', ['can', 'haz']]
def f(a):
itr = iter(a)
return [f(a) if isinstance(x, list) else {'key': x, 'val': next(itr)} for x in itr]
# >>> f(a)
# [{'key': 'foo', 'val': 'bar'}, [{'key': 'can', 'val': 'haz'}]]
更新:
好吧,我必须说这让我有点头疼,但因为这是一个有趣的问题和学习新东西的好机会,所以就在这里。
一个函数 正是1 你想要的,因为你有一些递归操作的问题:
With your precise function and input I get RecursionError: maximum recursion depth exceeded while calling a Python object
它没有递归。我确定这不是 最终 解决方案,但它有效:
from functools import reduce
import operator
def traverse(lst):
stack = [lst]
res = [[]]
substack = stack[0]
subres = res[0]
depth = 0
while stack:
if substack:
if isinstance(substack[0], list):
substack = substack[0]
subres.append([])
subres = subres[-1]
depth += 1
else:
if len(substack) > 1 and not isinstance(substack[1], list):
subres.append({'key': substack.pop(0), 'val': substack.pop(0)})
else:
subres.append(substack.pop(0))
else:
substack = reduce(operator.getitem, [0] * depth, stack)
subres = reduce(operator.getitem, [-1] * depth, res)
depth -= 1
substack.pop(0)
return res[0]
1.如果您只将列表列表传递给函数,我不确定您应该如何知道输出示例中 dict 键的确切预名,所以我会留给您。
下面乱七八糟的,不过solution()
里面的核心算法好像还不错。我不能说我喜欢那里的 sentinel
但是...它让其他一切变得整洁。
https://repl.it/@altendky/ChartreuseWeightyRoot-10
import functools
import itertools
import random
import string
import attr
import toolz
@attr.s(frozen=True)
class Example:
source = attr.ib()
target = attr.ib()
group_handler = attr.ib()
def random_example():
a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z = tuple(
(round(abs(random.random()) ** 10, 4)
if random.randint(0, 1) % 2 == 0
else random.randint(20, 50)
if random.randint(0, 1) % 2 == 0
else ('foo', 'bar', 'can', 'haz', 'bzr')[random.randint(0, 4)])
for c in string.ascii_lowercase)
l1 = [a, b, c, d, e, f, g, [h, i, j, k],
l, m, n, [o, p, q, r, [s, t, u, v, w, x, y, z], a, b], c, d, e]
auauughhghhhh = [
{f'{a}_key': a, f'{a}_val': b,
f'{c}_key': c, f'{c}_val': d,
f'{e}_key': e, f'{e}_val': f},
g,
[
{f'{h}_key': h, f'{h}_val': i,
f'{j}_key': j, f'{j}_val': k}
],
{f'{l}_key': l, f'{l}_val': m},
n,
[
{f'{o}_key': o, f'{o}_val': p,
f'{q}_key': q, f'{q}_val': r},
[
{f'{s}_key': s, f'{s}_val': t,
f'{u}_key': u, f'{u}_val': v,
f'{w}_key': w, f'{w}_val': x,
f'{y}_key': y, f'{y}_val': z}
],
{f'{a}_key': a, f'{a}_val': b}
],
{f'{c}_key': c, f'{c}_val': d},
e
]
g = lambda k,v: {'{}_key'.format(k): k, '{}_val'.format(k): v}
return Example(
source=l1,
target=auauughhghhhh,
group_handler=functools.partial(process_group, paired_sequence_handler=lambda s: build_dict_by_update(s, g)),
)
def process_group(group, paired_sequence_handler):
processed_group = []
if len(group) == 0:
return processed_group
odd = (len(group) % 2) != 0
raw_pairs = group[:-1] if odd else group
pairs = toolz.partition_all(2, raw_pairs)
result = paired_sequence_handler(pairs)
processed_group.append(result)
if odd:
processed_group.append(group[-1])
return processed_group
def build_dict_by_update(sequence, pair_handler):
result = {}
for pair in sequence:
result.update(pair_handler(*pair))
return result
examples = [
Example(
source=['foo', 'bar', ['can', 'haz']],
target=[{'key': 'foo', 'val': 'bar'}, [{'key': 'can', 'val': 'haz'}]],
group_handler=functools.partial(process_group, paired_sequence_handler=lambda s: build_dict_by_update(s, lambda k,v: {'key': k, 'val': v})),
),
random_example(),
]
def solution(source, group_handler):
built = []
group = []
sentinel = object()
for value in itertools.chain(source, [sentinel]):
if not isinstance(value, list) and value is not sentinel:
group.append(value)
continue
built.extend(group_handler(group))
group = []
if value is sentinel:
break
result = solution(
source=value,
group_handler=group_handler,
)
built.append(result)
return built
for example in examples:
result = solution(
source=example.source,
group_handler=example.group_handler,
)
succeeded = result == example.target
print('?', succeeded)
if not succeeded:
print('? ', example.target)
print('? ', result)
a = ['foo', 'bar', ['can', 'haz']]
希望对每对字符串应用一个函数,替换它们,包括列表中的字符串。例如,
f = lambda k,v: {'key': k, 'val': v}
这样 f(a)
就会变成:
[{'key': 'foo', 'val': 'bar'}, [{'key': 'can', 'val': 'haz'}]]
以上 a
只有 2 个维度,但我会对 k 个维度感兴趣。在发现用 dict
或其他 f
替换每个层次结构级别的所有非列表元素不是正确的用例之前,就开始与 boltons.iterutils.remap
一起破解某些东西……
编辑:另一个例子
# create some random variables, alternative: `locals().update({c: (round(…`
a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z = tuple(
(round(abs(random()) ** 10, 4)
if randint(0, 1) % 2 == 0
else randint(20, 50)
if randint(0, 1) % 2 == 0
else ('foo', 'bar', 'can', 'haz', 'bzr')[randint(0, 4)])
for c in ascii_lowercase)
l1 = [a, b, c, d, e, f, g, [h, i, j, k],
l, m, n, [o, p, q, r, [s, t, u, v, w, x, y, z], a, b], c, d, e]
g = lambda k,v: {'{}_key'.format(k): k, '{}_val'.format(k): v}
当有一对彼此相邻时,它应该对其应用类型构造函数 T,并直接连接(我有一个 add_to
支持字典、列表等的函数)任何前面的adjacent——没有列表 inbetwixt——否则原始标量应该以与之前相同的层次结构连接到列表中。这是 g(l1)
的预期输出,不包括变量评估:
[
{'a_key': a, 'a_val': b,
'c_key': c, 'c_val': d,
'e_key': e, 'e_val': f},
g,
[
{'h_key': h, 'h_val': i,
'j_key': j, 'j_val': k}
],
{'l_key': l, 'l_val': m},
n,
[
{'o_key': o, 'o_val': p,
'q_key': q, 'q_val': r},
[
{'s_key': s, 's_val': t,
'u_key': u, 'u_val': v,
'w_key': w, 'w_val': x,
'y_key': y, 'y_val': z}
],
{'a_key': a, 'a_val': b}
],
{'c_key': c, 'c_val': d},
e
]
您将需要递归以支持未定义数量的级别。
假设您的级别在每个级别的列表中始终有 2 或 3 个项目,则递归函数可能如下所示:
a = ['foo', 'bar', ['can', 'haz']]
def f(a):
k,v,b,*_ = a+[None]
result = [{"key":k,"val":v}]
if b: result.append(f(b))
return result
输出:
print(f(a))
# [{'key': 'foo', 'val': 'bar'}, [{'key': 'can', 'val': 'haz'}]]
b = ['foo', 'bar', ['can', 'haz', ['boo','yah',['dino','dog']]]]
print(f(b))
[
{'key': 'foo', 'val': 'bar'},
[
{'key': 'can', 'val': 'haz'},
[
{'key': 'boo', 'val': 'yah'},
[
{'key': 'dino', 'val': 'dog'}
]
]
]
]
假设每个列表的连续内容总是键值对或列表:
a = ['foo', 'bar', ['can', 'haz']]
def f(a):
itr = iter(a)
return [f(a) if isinstance(x, list) else {'key': x, 'val': next(itr)} for x in itr]
# >>> f(a)
# [{'key': 'foo', 'val': 'bar'}, [{'key': 'can', 'val': 'haz'}]]
更新:
好吧,我必须说这让我有点头疼,但因为这是一个有趣的问题和学习新东西的好机会,所以就在这里。
一个函数 正是1 你想要的,因为你有一些递归操作的问题:
With your precise function and input I get
RecursionError: maximum recursion depth exceeded while calling a Python object
它没有递归。我确定这不是 最终 解决方案,但它有效:
from functools import reduce
import operator
def traverse(lst):
stack = [lst]
res = [[]]
substack = stack[0]
subres = res[0]
depth = 0
while stack:
if substack:
if isinstance(substack[0], list):
substack = substack[0]
subres.append([])
subres = subres[-1]
depth += 1
else:
if len(substack) > 1 and not isinstance(substack[1], list):
subres.append({'key': substack.pop(0), 'val': substack.pop(0)})
else:
subres.append(substack.pop(0))
else:
substack = reduce(operator.getitem, [0] * depth, stack)
subres = reduce(operator.getitem, [-1] * depth, res)
depth -= 1
substack.pop(0)
return res[0]
1.如果您只将列表列表传递给函数,我不确定您应该如何知道输出示例中 dict 键的确切预名,所以我会留给您。
下面乱七八糟的,不过solution()
里面的核心算法好像还不错。我不能说我喜欢那里的 sentinel
但是...它让其他一切变得整洁。
https://repl.it/@altendky/ChartreuseWeightyRoot-10
import functools
import itertools
import random
import string
import attr
import toolz
@attr.s(frozen=True)
class Example:
source = attr.ib()
target = attr.ib()
group_handler = attr.ib()
def random_example():
a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z = tuple(
(round(abs(random.random()) ** 10, 4)
if random.randint(0, 1) % 2 == 0
else random.randint(20, 50)
if random.randint(0, 1) % 2 == 0
else ('foo', 'bar', 'can', 'haz', 'bzr')[random.randint(0, 4)])
for c in string.ascii_lowercase)
l1 = [a, b, c, d, e, f, g, [h, i, j, k],
l, m, n, [o, p, q, r, [s, t, u, v, w, x, y, z], a, b], c, d, e]
auauughhghhhh = [
{f'{a}_key': a, f'{a}_val': b,
f'{c}_key': c, f'{c}_val': d,
f'{e}_key': e, f'{e}_val': f},
g,
[
{f'{h}_key': h, f'{h}_val': i,
f'{j}_key': j, f'{j}_val': k}
],
{f'{l}_key': l, f'{l}_val': m},
n,
[
{f'{o}_key': o, f'{o}_val': p,
f'{q}_key': q, f'{q}_val': r},
[
{f'{s}_key': s, f'{s}_val': t,
f'{u}_key': u, f'{u}_val': v,
f'{w}_key': w, f'{w}_val': x,
f'{y}_key': y, f'{y}_val': z}
],
{f'{a}_key': a, f'{a}_val': b}
],
{f'{c}_key': c, f'{c}_val': d},
e
]
g = lambda k,v: {'{}_key'.format(k): k, '{}_val'.format(k): v}
return Example(
source=l1,
target=auauughhghhhh,
group_handler=functools.partial(process_group, paired_sequence_handler=lambda s: build_dict_by_update(s, g)),
)
def process_group(group, paired_sequence_handler):
processed_group = []
if len(group) == 0:
return processed_group
odd = (len(group) % 2) != 0
raw_pairs = group[:-1] if odd else group
pairs = toolz.partition_all(2, raw_pairs)
result = paired_sequence_handler(pairs)
processed_group.append(result)
if odd:
processed_group.append(group[-1])
return processed_group
def build_dict_by_update(sequence, pair_handler):
result = {}
for pair in sequence:
result.update(pair_handler(*pair))
return result
examples = [
Example(
source=['foo', 'bar', ['can', 'haz']],
target=[{'key': 'foo', 'val': 'bar'}, [{'key': 'can', 'val': 'haz'}]],
group_handler=functools.partial(process_group, paired_sequence_handler=lambda s: build_dict_by_update(s, lambda k,v: {'key': k, 'val': v})),
),
random_example(),
]
def solution(source, group_handler):
built = []
group = []
sentinel = object()
for value in itertools.chain(source, [sentinel]):
if not isinstance(value, list) and value is not sentinel:
group.append(value)
continue
built.extend(group_handler(group))
group = []
if value is sentinel:
break
result = solution(
source=value,
group_handler=group_handler,
)
built.append(result)
return built
for example in examples:
result = solution(
source=example.source,
group_handler=example.group_handler,
)
succeeded = result == example.target
print('?', succeeded)
if not succeeded:
print('? ', example.target)
print('? ', result)