英文:
Group element in list based on conditions and indexes
问题
我有一组由姓名和角色组成的列表。然而,列表之间没有真正的逻辑关系。
例如,我有这个列表:
l = ['john', 'owner', 'mark', 'manager', 'alex', 'steve', 'employee', 'manager'] # 最后一个角色不应分配给任何人
我想将每个人分配到列表中紧邻或最接近他的角色。
期望的输出应该类似于:
output = [['john', 'owner'], ['mark', 'manager'], ['alex', 'employee'], ['steve', 'employee']]
我的猜想是向列表元素添加索引,然后根据一组条件确定在列表中查找的元素附近的元素。
这是我的脚本的一部分:
parties_role = [(idx, item) for idx, item in enumerate(l)]
for item in parties_role:
if "owner" not in str(item[1]) and 'manager' not in str(item[1]) and 'employee' not in str(item[1]):
name = str(item[1])
代码的其余部分应查看包含关键词owner
,manager
和employee
的列表项,并根据索引为当前的name
变量分配最接近的角色。
英文:
I have a set of lists composed of names and role. However, there is no real logic between how the list are organized.
For instance, I have this list :
l = ['john', 'owner', 'mark', 'manager', 'alex', 'steve', 'employee', 'manager'] #the last role shouldn't be assigned to anyone
I want to assign each person the role that is located next to it in the list or the closest one from left to right.
The desired output should be something like :
output = [['john', 'owner'], ['mark', 'manager'], ['alex', 'employee'], ['steve', 'employee']]
My guess was to add indexes to the list elements, and than check which element based on a set of condition was closest to the list element I was looking at.
This is part of my script :
parties_role = [(idx, item) for idx,item in enumerate(l)]
for item in parties_role:
if "owner" not in str(item[1]) and 'manager' not in str(item[1]) and 'employee' not in str(item[1]):
name = str(item[1])
The rest of the code shoud look at the list items that contain the keywords owner
, manager
and employee
and assign to the current name
variable the closest role based on the index.
答案1
得分: 3
# 使用在反转输入上的简单循环,你可以为一个或多个名字分配紧随其后的角色:
roles = {'owner', 'manager', 'employee'}
result = []
role = None
for x in reversed(l):
if x in roles:
role = x
continue
result.append([x, role])
如果顺序很重要
result = result[::-1]
输出:
[['john', 'owner'],
['mark', 'manager'],
['alex', 'employee'],
['steve', 'employee'],
]
<details>
<summary>英文:</summary>
Using a simple loop on the reversed input, you can assign the role that is immediately after one or several names:
roles = {'owner', 'manager', 'employee'}
result = []
role = None
for x in reversed(l):
if x in roles:
role = x
continue
result.append([x, role])
if order is important
result = result[::-1]
Output:
[['john', 'owner'],
['mark', 'manager'],
['alex', 'employee'],
['steve', 'employee'],
]
</details>
# 答案2
**得分**: 1
让我们创建一个"roles"集合:
```python
roles = {'owner', 'manager', 'employee'}
现在,让我们使用 reduce
。我们的累加器是一个包含两个列表的元组:最终结果列表和第二个列表是迄今为止读取的名称的"bucket"。当它遇到一个角色时,它将这些名称映射到该角色并将它们添加到结果列表中。
from functools import reduce
grouped = reduce(
lambda acc, x:
(acc[0] + [[y, x] for y in acc[1]], []) if x in roles else
(acc[0], acc[1] + [x]),
l,
([], [])
)
grouped[0]
[[ 'john', 'owner'], [ 'mark', 'manager'], [ 'alex', 'employee'], [ 'steve', 'employee']]
英文:
Let's create a set of "roles":
roles = {'owner', 'manager', 'employee'}
Now, let's use reduce
. Our accumulator is a tuple with two lists: the final result and the second list is a "bucket" of names read thus far. When it encounters a role, it maps those names to that role and adds them to the result list.
>>> from functools import reduce
>>> grouped = reduce(
... lambda acc, x:
... (acc[0] + [[y, x] for y in acc[1]], []) if x in roles else
... (acc[0], acc[1] + [x]),
... l,
... ([], [])
... )
>>> grouped[0]
[['john', 'owner'], ['mark', 'manager'], ['alex', 'employee'], ['steve', 'employee']]
答案3
得分: 1
这段代码可以从一组已知的角色开始...你需要某种方法来区分名字和角色,所以我假设这是可能的。有了这个,你可以根据字符串是名字还是角色进行分组。这应该会给你交替的名字和角色组。然后进行zip和组装:
from itertools import groupby
roles = {'owner', 'manager', 'employee'}
l = ['john', 'owner', 'mark', 'manager', 'alex', 'steve', 'employee', 'manager']
groups = (list(v) for _, v in groupby(l, key=lambda s: s in roles))
result = [[name, list(roles)[0]] for names, roles in zip(groups, groups) for name in names]
这将产生一个名为result
的结果:
[['john', 'owner'],
['mark', 'manager'],
['alex', 'employee'],
['steve', 'employee']]
它假设原始列表以一个名字开始。
英文:
You could start with a set of known roles...you need some way to tell names from roles, so I assume this is possible. With that you can group by whether the string is a name or a role. This should give you alternating groups of names and roles. Then zip and assemble:
from itertools import groupby
roles = {'owner', 'manager', 'employee'}
l = ['john', 'owner', 'mark', 'manager', 'alex', 'steve', 'employee', 'manager']
groups = (list(v) for _, v in groupby(l, key=lambda s: s in roles))
result = [[name, roles[0]] for names, roles in zip(groups, groups) for name in names]
This produces a result
of:
[['john', 'owner'],
['mark', 'manager'],
['alex', 'employee'],
['steve', 'employee']]
It makes the assumption that the original list starts with a name.
答案4
得分: 1
- 定义哪些字符串是角色,哪些不是(例如,创建一个有效
roles
的集合,假设其他一切都是名称)。 - 迭代
l
中的每个name
,使用enumerate
来跟踪索引。- 对于每个
name
,找到l
中下一个(在名称索引之后)是角色的元素。
- 对于每个
>>> l = ['john', 'owner', 'mark', 'manager', 'alex', 'steve', 'employee', 'manager']
>>> roles = {'owner', 'manager', 'employee'}
>>> [[name, next(e for e in l[i:] if e in roles)] for i, name in enumerate(l) if name not in roles]
[['john', 'owner'], ['mark', 'manager'], ['alex', 'employee'], ['steve', 'employee']]
英文:
I might do it like this:
- Define which strings are roles and which aren't (e.g. create a set of valid
roles
, assume everything else is a name). - Iterate over each
name
inl
, usingenumerate
to track the index.- For each
name
, find thenext
element inl
(after the name's index) that's a role.
- For each
>>> l = ['john', 'owner', 'mark', 'manager', 'alex', 'steve', 'employee', 'manager']
>>> roles = {'owner', 'manager', 'employee'}
>>> [[name, next(e for e in l[i:] if e in roles)] for i, name in enumerate(l) if name not in roles]
[['john', 'owner'], ['mark', 'manager'], ['alex', 'employee'], ['steve', 'employee']]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论