Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 将列表拆分为具有相等值的较小列表_Python - Fatal编程技术网

Python 将列表拆分为具有相等值的较小列表

Python 将列表拆分为具有相等值的较小列表,python,Python,我希望将一个列表转换为更小的相等值列表。我举的一个例子是: ["a", "a", "a", "b", "b", "c", "c", "c", "c"] 到 您认为最有效的方法是什么?您可以使用以下方法解决此问题: >>> from itertools import groupby >>> [list(grp) for k, grp in groupby(["a", "a", "a", "b", "b", "c", "c", "c", "c"])] [['a

我希望将一个列表转换为更小的相等值列表。我举的一个例子是:

["a", "a", "a", "b", "b", "c", "c", "c", "c"] 

您认为最有效的方法是什么?

您可以使用以下方法解决此问题:

>>> from itertools import groupby
>>> [list(grp) for k, grp in groupby(["a", "a", "a", "b", "b", "c", "c", "c", "c"])]
[['a', 'a', 'a'], ['b', 'b'], ['c', 'c', 'c', 'c']]
它只对连续相等的元素进行分组,但在您的情况下这似乎足够了。

您可以使用以下方法来解决此问题:

>>> from itertools import groupby
>>> [list(grp) for k, grp in groupby(["a", "a", "a", "b", "b", "c", "c", "c", "c"])]
[['a', 'a', 'a'], ['b', 'b'], ['c', 'c', 'c', 'c']]

它只对连续相等的元素进行分组,但这在您的情况下似乎已经足够了。

您可以使用
集合。Counter

>>> lst = ["a", "a", "a", "b", "b", "c", "c", "c", "c"]
>>> import collections
>>> collections.Counter(lst).most_common()
[('c', 4), ('a', 3), ('b', 2)]
即使在值没有排序的情况下也可以这样做,它提供了一个非常紧凑的表示形式,您可以根据需要将其扩展到列表中:

>>> [[i]*n for i,n in collections.Counter(lst).most_common()]
[['c', 'c', 'c', 'c'], ['a', 'a', 'a'], ['b', 'b']]

您可以使用
collections.Counter

>>> lst = ["a", "a", "a", "b", "b", "c", "c", "c", "c"]
>>> import collections
>>> collections.Counter(lst).most_common()
[('c', 4), ('a', 3), ('b', 2)]
即使在值没有排序的情况下也可以这样做,它提供了一个非常紧凑的表示形式,您可以根据需要将其扩展到列表中:

>>> [[i]*n for i,n in collections.Counter(lst).most_common()]
[['c', 'c', 'c', 'c'], ['a', 'a', 'a'], ['b', 'b']]

虽然我个人认为,
itertools.groupby
是最方便的方式,但您要求提高效率,这应该比任何
itertools
选项都要快得多:

data = ["a", "a", "a", "b", "b", "c", "c", "c", "c"] 

lookup = {}  # lookup map
result = []
for element in data:
    if element not in lookup:
        target = lookup[element] = [element]
        result.append(target)
    else:
        lookup[element].append(element)

print(result)
# [['a', 'a', 'a'], ['b', 'b'], ['c', 'c', 'c', 'c']]
如果数据总是按顺序排列(即元素不混合),则可以在不使用查找表和使用列表理解的情况下进一步优化,以获得最佳性能

更新-一些关于效率和操作的澄清。如果您将测试设置为:

from itertools import groupby

def itools_func(data):
    return [list(grp) for k, grp in groupby(data)]

def manual_func(data):
    lookup = {}
    result = []
    for element in data:
        if element not in lookup:
            target = lookup[element] = [element]
            result.append(target)
        else:
            lookup[element].append(element)
    return result
问题在于,这两个函数不会返回相同的值:

test_data = ["a", "a", "b", "c", "c", "b", "a"]

itools_func(test_data)  # [['a', 'a'], ['b'], ['c', 'c'], ['b'], ['a']]
manual_func(test_data)  # [['a', 'a', 'a'], ['b', 'b'], ['c', 'c']]

从OP的问题中,我了解到他想要后一个(基于他的评论“我对列表进行排序以使值连续”),因为使用排序的列表可以轻松得多。因此,如果我们为这些函数提供一个非常长的列表:

test_data = ["a", "a", "a", "b", "b", "c", "c", "c", "c"] * 10000  # 10000 x the original
在我的系统上,它的时钟如下所示:

itools_func - 100 loops: 2.668s, per loop: 26.68ms
manual_func - 100 loops: 1.005s, per loop: 10.05ms
但是,这对于
itertools.groopby
来说是一个不利的设置。如果要对数据进行如下排序:

test_data = ["a"] * 3000 + ["b"] * 2000 + ["c"] * 40000
随着C后端的出现,情况有了很大的不同:

itools_func - 1000 loops: 656.3ms, per loop: 656.3µs
manual_func - 1000 loops: 4.816s, per loop: 4.816ms

当对数据进行排序时,手动功能可以进一步优化,但它很难打败
itertools
在引擎盖下的功能。

而我个人选择
itertools.groupby
作为最方便的方式,您要求提高效率,这应该比任何
itertools
选项都要快得多:

data = ["a", "a", "a", "b", "b", "c", "c", "c", "c"] 

lookup = {}  # lookup map
result = []
for element in data:
    if element not in lookup:
        target = lookup[element] = [element]
        result.append(target)
    else:
        lookup[element].append(element)

print(result)
# [['a', 'a', 'a'], ['b', 'b'], ['c', 'c', 'c', 'c']]
如果数据总是按顺序排列(即元素不混合),则可以在不使用查找表和使用列表理解的情况下进一步优化,以获得最佳性能

更新-一些关于效率和操作的澄清。如果您将测试设置为:

from itertools import groupby

def itools_func(data):
    return [list(grp) for k, grp in groupby(data)]

def manual_func(data):
    lookup = {}
    result = []
    for element in data:
        if element not in lookup:
            target = lookup[element] = [element]
            result.append(target)
        else:
            lookup[element].append(element)
    return result
问题在于,这两个函数不会返回相同的值:

test_data = ["a", "a", "b", "c", "c", "b", "a"]

itools_func(test_data)  # [['a', 'a'], ['b'], ['c', 'c'], ['b'], ['a']]
manual_func(test_data)  # [['a', 'a', 'a'], ['b', 'b'], ['c', 'c']]

从OP的问题中,我了解到他想要后一个(基于他的评论“我对列表进行排序以使值连续”),因为使用排序的列表可以轻松得多。因此,如果我们为这些函数提供一个非常长的列表:

test_data = ["a", "a", "a", "b", "b", "c", "c", "c", "c"] * 10000  # 10000 x the original
在我的系统上,它的时钟如下所示:

itools_func - 100 loops: 2.668s, per loop: 26.68ms
manual_func - 100 loops: 1.005s, per loop: 10.05ms
但是,这对于
itertools.groopby
来说是一个不利的设置。如果要对数据进行如下排序:

test_data = ["a"] * 3000 + ["b"] * 2000 + ["c"] * 40000
随着C后端的出现,情况有了很大的不同:

itools_func - 1000 loops: 656.3ms, per loop: 656.3µs
manual_func - 1000 loops: 4.816s, per loop: 4.816ms

当对数据进行排序时,手动功能可以进一步优化,但它很难打败
itertools
在引擎盖下的功能。

另一种获得所需输出的方式是使用
集合
模块中的
defaultdict
(使用此方法的最佳时间为:~=0.02s,与使用
groupby
相同):

所以,你现在要做的是:

list(b.values())
>>> [['a', 'a', 'a'], ['b', 'b'], ['c', 'c', 'c', 'c']]

获得所需输出的另一种方式是使用
collections
模块中的
defaultdict
(使用此方法的最佳时间为:~=0.02s,与使用
groupby
相同):

所以,你现在要做的是:

list(b.values())
>>> [['a', 'a', 'a'], ['b', 'b'], ['c', 'c', 'c', 'c']]

相等值是否必须连续?我对列表进行排序以使值连续?我对列表进行排序以使值连续。在分组之前,可以(应该?)对列表进行排序。这取决于确切的要求。如果它应该将相等的连续元素分组,则为“否”;如果它应该将所有相等的值(总体)分组并保持顺序,则有更好的方法使用
OrderedDict
计数器
。如果顺序不重要,相等的元素不是连续的,那么排序是一种有效的策略。对于给定的示例,最有效的方法就是使用
groupby
(不进行排序):)同意。OP只是说他们对列表进行排序是为了方便。人们可以(应该)在分组之前对列表进行排序。这取决于具体的要求。如果它应该将相等的连续元素分组,则为“否”;如果它应该将所有相等的值(总体)分组并保持顺序,则有更好的方法使用
OrderedDict
计数器
。如果顺序不重要,相等的元素不是连续的,那么排序是一种有效的策略。对于给定的示例,最有效的方法就是使用
groupby
(不进行排序):)同意。OP刚才说他们对列表进行排序是为了方便。你知道如何访问每个元素的计数器值吗?在本例中,4、3和2序列只需使用:
[n代表collections.Counter(lst)中的i,n.most_common()]
您知道如何访问每个元素的计数器值吗?在这种情况下,4、3和2序列只需使用:
[n代表集合中的i,n.Counter(lst).most_common()]
好吧,如果您关心效率,您可能应该使用
defaultdict
,或者至少使用普通
dict
.setdefault
方法,而不是检查
如果元素不在查找中:
。还有,我很好奇你为什么说这会快得多。你有时间安排吗<毕竟,代码>itertools.groupby是用C编写的。对于非常短的输入来说,这只会“更”有效。如果<代码>数据很大或很大,那么速度会慢得多。@juanpa.arrivillaga@MSeifert-我已经用一些数字更新了我的帖子。至于为什么不使用
de