Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/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_Sorting - Fatal编程技术网

Python—通过列表进行求和和和分组

Python—通过列表进行求和和和分组,python,sorting,Python,Sorting,我有一个很大的数字列表,如下所示: a = [133000, 126000, 123000, 108000, 96700, 96500, 93800, 93200, 92100, 90000, 88600, 87000, 84300, 82400, 80700, 79900, 79000, 78800, 76100, 75000, 15300, 15200, 15100, 8660, 8640, 8620, 8530, 2590, 2590, 2580, 2550, 2540, 2540

我有一个很大的数字列表,如下所示:

a = [133000, 126000, 123000, 108000, 96700, 96500, 93800, 
 93200, 92100, 90000, 88600, 87000, 84300, 82400, 80700,
 79900, 79000, 78800, 76100, 75000, 15300, 15200, 15100,
 8660, 8640, 8620, 8530, 2590, 2590, 2580, 2550, 2540, 2540, 
 2510, 2510, 1290, 1280, 1280, 1280, 1280, 951, 948, 948,
 947, 946, 945, 609, 602, 600, 599, 592, 592, 592, 591, 583]  
我想做的是逐个循环浏览这个列表,检查一个值是否高于某个阈值(例如40000)。如果它高于此阈值,我们将该值放入一个新列表中,并将其忘掉。否则,我们将等待值的总和超过阈值,然后将值放入列表中,然后继续循环。最后,如果最终值的总和不到阈值,我们只需将它们添加到最后一个列表中

如果我不清楚,考虑一个简单的例子,阈值为15</p>

[20, 10, 9, 8, 8, 7, 6, 2, 1]
最终列表应如下所示:

[[20], [10, 9], [8, 8], [7, 6, 2, 1]]
我在数学和python方面真的很差,我已经不知所措了。我提出了一些基本代码,但实际上不起作用:

def sortthislist(list):
    list = a
    newlist = []
    for i in range(len(list)):
        while sum(list[i]) >= 40000:
            newlist.append(list[i])
    return newlist

任何帮助都将不胜感激。很抱歉写了这么长的文章。

下面的函数将接受您的输入列表和一些检查限制,然后输出已排序的列表:

a = [20, 10, 9, 8, 8, 7, 6, 2, 1]

def func(a, lim):
    out = []
    temp = []
    for i in a:
        if i > lim:
            out.append([i])
        else:
            temp.append(i)
            if sum(temp) > lim:
                out.append(temp)
                temp = []
    return out

print(func(a, 15))
# [[20], [10, 9], [8, 8], [7, 6, 2, 1]]
使用Python,您可以对列表本身进行迭代,而不是对其索引进行迭代,因此您可以看到我对a中的I使用
,而不是对范围(len(a))中的I使用

在函数
out
中,是要在末尾返回的列表
temp
是一个临时列表,在
temp
的总和超过您的
lim
值之前,该
temp
将被追加到
out
并替换为空列表。

希望这会有所帮助:)

def group(L, threshold):
    answer = []
    start = 0
    sofar = L[0]
    for i,num in enumerate(L[1:],1):
        if sofar >= threshold:
            answer.append(L[start:i])
            sofar = L[i]
            start = i
        else:
            sofar += L[i]
    if i<len(L) and sofar>=threshold:
        answer.append(L[i:])
    return answer
结果是:

[[20], [10, 3, 9], [7, 6, 5], [4]]

还有另一种方法:

def group_by_sum(a, lim):
    out = []
    group = None
    for i in a:
        if group is None:
            group = []
            out.append(group)

        group.append(i)

        if sum(group) > lim:
            group = None
    return out

print(group_by_sum(a, 15))

我们已经有了很多可行的答案,但这里还有两种方法

我们可以使用来收集这样的组,因为有一个了解组内容的有状态累加器。我们最终得到一组(键,组)对,因此一些额外的过滤只会得到组。此外,由于itertools提供迭代器,我们将它们转换为列表以进行打印

from itertools import groupby

class Thresholder:
  def __init__(self, threshold):
    self.threshold=threshold
    self.sum=0
    self.group=0
  def __call__(self, value):
    if self.sum>self.threshold:
      self.sum=value
      self.group+=1
    else:
      self.sum+=value
    return self.group
print [list(g) for k,g in groupby([20, 10, 9, 8, 8, 7, 6, 2, 1], Thresholder(15))]
该操作也可以作为单个reduce调用完成:

def accumulator(result, value):
  last=result[-1]
  if sum(last)>threshold:
    result.append([value])
  else:
    last.append(value)
  return result
threshold=15
print reduce(accumulator, [20, 10, 9, 8, 8, 7, 6, 2, 1], [[]])
由于重复调用sum(),此版本无法扩展到多个值,阈值的全局变量相当笨拙。此外,调用它以获得一个空列表仍然会留下一个空组


编辑:问题逻辑要求将高于阈值的值放入它们自己的组中(不与收集的较小值共享)。在编写这些版本时,我没有想到这一点,但Ffisegydd接受的答案解决了这一问题。如果输入数据按降序排序,则没有有效的差异,因为所有样本数据似乎都是降序的

您使用的是什么版本的Python?
from itertools import groupby

class Thresholder:
  def __init__(self, threshold):
    self.threshold=threshold
    self.sum=0
    self.group=0
  def __call__(self, value):
    if self.sum>self.threshold:
      self.sum=value
      self.group+=1
    else:
      self.sum+=value
    return self.group
print [list(g) for k,g in groupby([20, 10, 9, 8, 8, 7, 6, 2, 1], Thresholder(15))]
def accumulator(result, value):
  last=result[-1]
  if sum(last)>threshold:
    result.append([value])
  else:
    last.append(value)
  return result
threshold=15
print reduce(accumulator, [20, 10, 9, 8, 8, 7, 6, 2, 1], [[]])