Python 创建列表列表,其中第一项长度为 1,第二项长度为 n?
Python creating list of lists where first item is of length one and the second item is of length n?
我在 python 中创建列表列表时遇到问题。假设我有以下列表:
fruitlist = [('Vendor A', 'Apples'),
('Vendor B', 'Apples'),
('Vendor C', 'Bananas'),
('Vendor A', 'Grapes'),
('Vendor A', 'Bananas'),
('Vendor B', 'Oranges')]
我想要做的是创建这样的列表:[[Vendor A, (Apples, Grapes, Bananas)], [Vendor B, (Apples, Oranges)], [Vendor C, (Bananas)]]
所以基本上是供应商,然后是他们的产品。这是我目前拥有的代码,它基本上遍历并仅提取供应商列表,然后循环遍历并获取每个产品,但是,输出并不是我想要的。
vendors = list(set([x[0] for x in fruitlist]))
# this creates a list of just vendors:
output = [[] for x in range (len(vendors))]
#This creates a list with 3 empty lists inside (one for each vendor) where my output will be housed
for x in range(0,len(vendors)):
for y in range(0,len(fruitlist)):
if fruitlist[y][0] == vendors[x]:
output[x].append(fruitlist[y][1])
输出看起来像这样:
[['Apples', 'Oranges'], ['Apples', 'Grapes', 'Bananas'], ['Bananas']]
所以输出现在按供应商细分,每个供应商的产品现在都在自己的列表中,但现在我必须弄清楚如何在其中插入供应商名称,但我就是做不到。如果我在 for 循环的附加部分中包含供应商名称,
output[x].append((fruitlist[y][0],fruitlist[y][1]))
它重复每个水果的供应商名称。如果我使用 insert 方法,它似乎创建了一个全新的项目,并增加了列表的长度。我试过一些东西,我试过谷歌搜索,但我无法找出正确的措辞。如果有人能指出我正确的方向,我将不胜感激。
也有人可以解释为什么当我查找供应商时:
['Vendor B', 'Vendor A', 'Vendor C']
它把 "B" 放在 "A" 前面?在我原来的列表中 A 是第一个,set 函数是否随机分配顺序?
集只是元素的集合,没有像列表那样的顺序。
我写这篇文章的方式是创建一个字典,然后,当我们将它转换为列表时,我们可以对其进行排序以匹配输入顺序。
fruitlist = [('Vendor A', 'Apples'),
('Vendor B', 'Apples'),
('Vendor C', 'Bananas'),
('Vendor A', 'Grapes'),
('Vendor A', 'Bananas'),
('Vendor B', 'Oranges')]
vendors = {}
for vendor, fruit in fruitlist:
vendors.setdefault(vendor, []).append(fruit)
ordered_fruitlist_vendors = [t[0] for t in fruitlist]
vendors_list = [[k, tuple(v)] for k,v in vendors.items()]
vendors_list.sort(key=lambda t: ordered_fruitlist_vendors.index(t[0]))
给出 vendors_list
为:
[['Vendor A', ('Apples', 'Grapes', 'Bananas')], ['Vendor B', ('Apples', 'Oranges')], ['Vendor C', ('Bananas',)]]
但是我怀疑是否有必要将整洁的字典转换为这个笨重的包含元组的 2 元素列表。您肯定希望能够在 O(1)
时间内使用 vendors['Vendor A']
从供应商那里取回水果,而不必遍历 O(n)
的列表?无论如何,这两种方法现在都是可选的!
setdefault
的解释。
字典的setdefault
方法有两个参数——一个键和一个值。如果键已经存在于字典中,则返回当前值,否则使用传递给函数的值创建键并返回该值。
例如:
>>> d = {1:2}
>>> d.setdefault(1,3)
2
>>> d
{1: 2}
>>> d.setdefault(3,4)
4
>>> d
{1: 2, 3: 4}
因此,使用此方法的一个巧妙技巧是将键设置为空列表 ([]
)。然后如果我们还没有那个键(在我们的例子中还没有看到供应商),那么返回一个空列表。否则,我们将获得对列表的引用,其中包含到目前为止我们看到的所有该供应商的水果。美妙之处在于,我们可以将我们的新水果添加到 无论返回什么 并且将为该供应商创建一个新条目并附加新水果,或者如果该供应商已经存在,我们只会附加到先前创建的列表中。
这意味着我们只需要迭代 fruitlist
一次,这样解决方案是有效的。
该方法与列表一起使用的另一个示例:
>>> d = {}
>>> d.setdefault(1, []).append(2)
>>> d
{1: [2]}
>>> d.setdefault(1, []).append(3)
>>> d.setdefault(1, []).append(4)
>>> d
{1: [2, 3, 4]}
>>> d.setdefault(2, []).append(3)
>>> d.setdefault(2, []).append(3)
>>> d.setdefault(2, []).append(3)
>>> d
{1: [2, 3, 4], 2: [3, 3, 3]}
(你看,没有字典)
数据
In [15]: fruitlist = [('Vendor A', 'Apples'),
...: ('Vendor B', 'Apples'),
...: ('Vendor C', 'Bananas'),
...: ('Vendor A', 'Grapes'),
...: ('Vendor A', 'Bananas'),
...: ('Vendor B', 'Oranges')]
输出列表,最初为空
In [16]: output = []
我们将使用 Python 的 for
循环的一个不常见的功能,即 else
子句。如果 for
主体正常结束,即没有 break
,则执行 else
子句的主体
In [17]: for vendor, fruit in fruitlist:
...: for sublist in output:
...: if sublist[0] == vendor:
...: sublist[1].append(fruit)
...: break
...: else:
...: output.append([vendor, [fruit]])
最终我们检查结果
In [18]: output
Out[18]:
[['Vendor A', ['Apples', 'Grapes', 'Bananas']],
['Vendor B', ['Apples', 'Oranges']],
['Vendor C', ['Bananas']]]
我不得不说原来的问题提到了子列表,其中第二个元素是一个元组,而我有一个列表,但是元组是不可变的...
您可以使用一个简单的 for
循环和一个 dictionary
无需使其过于复杂
fruits = [
('Vendor A', 'Apples'),
('Vendor B', 'Apples'),
('Vendor C', 'Bananas'),
('Vendor A', 'Grapes'),
('Vendor A', 'Bananas'),
('Vendor B', 'Oranges')
]
dicta = {}
for vendor, item in fruits:
if vendor not in dicta:
dicta[vendor] = [item]
else:
dicta[vendor].append(item)
print(dicta)
(xenial)vash@localhost:~/python/stack_overflow$ python3.7 fruits.py
{'Vendor A': ['Apples', 'Grapes', 'Bananas'], 'Vendor B': ['Apples', 'Oranges'], 'Vendor C': ['Bananas']}
我在 python 中创建列表列表时遇到问题。假设我有以下列表:
fruitlist = [('Vendor A', 'Apples'),
('Vendor B', 'Apples'),
('Vendor C', 'Bananas'),
('Vendor A', 'Grapes'),
('Vendor A', 'Bananas'),
('Vendor B', 'Oranges')]
我想要做的是创建这样的列表:[[Vendor A, (Apples, Grapes, Bananas)], [Vendor B, (Apples, Oranges)], [Vendor C, (Bananas)]]
所以基本上是供应商,然后是他们的产品。这是我目前拥有的代码,它基本上遍历并仅提取供应商列表,然后循环遍历并获取每个产品,但是,输出并不是我想要的。
vendors = list(set([x[0] for x in fruitlist]))
# this creates a list of just vendors:
output = [[] for x in range (len(vendors))]
#This creates a list with 3 empty lists inside (one for each vendor) where my output will be housed
for x in range(0,len(vendors)):
for y in range(0,len(fruitlist)):
if fruitlist[y][0] == vendors[x]:
output[x].append(fruitlist[y][1])
输出看起来像这样:
[['Apples', 'Oranges'], ['Apples', 'Grapes', 'Bananas'], ['Bananas']]
所以输出现在按供应商细分,每个供应商的产品现在都在自己的列表中,但现在我必须弄清楚如何在其中插入供应商名称,但我就是做不到。如果我在 for 循环的附加部分中包含供应商名称,
output[x].append((fruitlist[y][0],fruitlist[y][1]))
它重复每个水果的供应商名称。如果我使用 insert 方法,它似乎创建了一个全新的项目,并增加了列表的长度。我试过一些东西,我试过谷歌搜索,但我无法找出正确的措辞。如果有人能指出我正确的方向,我将不胜感激。
也有人可以解释为什么当我查找供应商时:
['Vendor B', 'Vendor A', 'Vendor C']
它把 "B" 放在 "A" 前面?在我原来的列表中 A 是第一个,set 函数是否随机分配顺序?
集只是元素的集合,没有像列表那样的顺序。
我写这篇文章的方式是创建一个字典,然后,当我们将它转换为列表时,我们可以对其进行排序以匹配输入顺序。
fruitlist = [('Vendor A', 'Apples'),
('Vendor B', 'Apples'),
('Vendor C', 'Bananas'),
('Vendor A', 'Grapes'),
('Vendor A', 'Bananas'),
('Vendor B', 'Oranges')]
vendors = {}
for vendor, fruit in fruitlist:
vendors.setdefault(vendor, []).append(fruit)
ordered_fruitlist_vendors = [t[0] for t in fruitlist]
vendors_list = [[k, tuple(v)] for k,v in vendors.items()]
vendors_list.sort(key=lambda t: ordered_fruitlist_vendors.index(t[0]))
给出 vendors_list
为:
[['Vendor A', ('Apples', 'Grapes', 'Bananas')], ['Vendor B', ('Apples', 'Oranges')], ['Vendor C', ('Bananas',)]]
但是我怀疑是否有必要将整洁的字典转换为这个笨重的包含元组的 2 元素列表。您肯定希望能够在 O(1)
时间内使用 vendors['Vendor A']
从供应商那里取回水果,而不必遍历 O(n)
的列表?无论如何,这两种方法现在都是可选的!
setdefault
的解释。
字典的setdefault
方法有两个参数——一个键和一个值。如果键已经存在于字典中,则返回当前值,否则使用传递给函数的值创建键并返回该值。
例如:
>>> d = {1:2}
>>> d.setdefault(1,3)
2
>>> d
{1: 2}
>>> d.setdefault(3,4)
4
>>> d
{1: 2, 3: 4}
因此,使用此方法的一个巧妙技巧是将键设置为空列表 ([]
)。然后如果我们还没有那个键(在我们的例子中还没有看到供应商),那么返回一个空列表。否则,我们将获得对列表的引用,其中包含到目前为止我们看到的所有该供应商的水果。美妙之处在于,我们可以将我们的新水果添加到 无论返回什么 并且将为该供应商创建一个新条目并附加新水果,或者如果该供应商已经存在,我们只会附加到先前创建的列表中。
这意味着我们只需要迭代 fruitlist
一次,这样解决方案是有效的。
该方法与列表一起使用的另一个示例:
>>> d = {}
>>> d.setdefault(1, []).append(2)
>>> d
{1: [2]}
>>> d.setdefault(1, []).append(3)
>>> d.setdefault(1, []).append(4)
>>> d
{1: [2, 3, 4]}
>>> d.setdefault(2, []).append(3)
>>> d.setdefault(2, []).append(3)
>>> d.setdefault(2, []).append(3)
>>> d
{1: [2, 3, 4], 2: [3, 3, 3]}
(你看,没有字典)
数据
In [15]: fruitlist = [('Vendor A', 'Apples'),
...: ('Vendor B', 'Apples'),
...: ('Vendor C', 'Bananas'),
...: ('Vendor A', 'Grapes'),
...: ('Vendor A', 'Bananas'),
...: ('Vendor B', 'Oranges')]
输出列表,最初为空
In [16]: output = []
我们将使用 Python 的 for
循环的一个不常见的功能,即 else
子句。如果 for
主体正常结束,即没有 break
else
子句的主体
In [17]: for vendor, fruit in fruitlist:
...: for sublist in output:
...: if sublist[0] == vendor:
...: sublist[1].append(fruit)
...: break
...: else:
...: output.append([vendor, [fruit]])
最终我们检查结果
In [18]: output
Out[18]:
[['Vendor A', ['Apples', 'Grapes', 'Bananas']],
['Vendor B', ['Apples', 'Oranges']],
['Vendor C', ['Bananas']]]
我不得不说原来的问题提到了子列表,其中第二个元素是一个元组,而我有一个列表,但是元组是不可变的...
您可以使用一个简单的 for
循环和一个 dictionary
无需使其过于复杂
fruits = [
('Vendor A', 'Apples'),
('Vendor B', 'Apples'),
('Vendor C', 'Bananas'),
('Vendor A', 'Grapes'),
('Vendor A', 'Bananas'),
('Vendor B', 'Oranges')
]
dicta = {}
for vendor, item in fruits:
if vendor not in dicta:
dicta[vendor] = [item]
else:
dicta[vendor].append(item)
print(dicta)
(xenial)vash@localhost:~/python/stack_overflow$ python3.7 fruits.py {'Vendor A': ['Apples', 'Grapes', 'Bananas'], 'Vendor B': ['Apples', 'Oranges'], 'Vendor C': ['Bananas']}