通过数字和将整数列表排序到列表中

时间:2016-11-01 21:55:25

标签: python list number-theory

我正在尝试编写一个Python函数,将一个数字列表排序为一个数字列表列表,每个子列表只包含数字,这些数字在较大列表中包含子列表索引的数字和。

因此,例如,对于1到25之间的所有数字,它应该产生这样的列表列表:

[[], [1, 10], [2, 11, 20], [3, 12, 21], [4, 13, 22], [5, 14, 23], [6, 15, 24], [7, 16], [8, 17], [9, 18], [19]]

到目前为止,我有以下代码:

def digit_sum(integer_data_type):
    int_string = str(integer_data_type)
    sum = 0
    for digits in int_string:
        sum += int(digits)
    return sum


def organize_by_digit_sum(integer_list):
    integer_list.sort()
    max_ds = 9*len(str(max(integer_list)))+1
    list_of_lists = []
    current_ds = 0
    while current_ds <= max_ds:
            current_list = []
            for n in integer_list:
                    if digit_sum(n) == current_ds:
                            current_list.append(n)
            list_of_lists.append(current_list)
            current_ds += 1
    return list_of_lists

显然,这是低效的,因为它必须遍历整个整数列表,反复遍历从0到最大数字总和的每个数字和。

此外,它最初假设最大数字总和是最大整数长度的9倍。为了清楚起见,我确实希望始终有一个可能的digit_sum为零的子列表,以便我可以通过列表列表的索引引用特定的数字和的子列表。

我希望函数只需要遍历列表中的每个整数一次,然后将其附加到正确的子列表中。

我将不胜感激任何帮助或见解。

4 个答案:

答案 0 :(得分:2)

如果您不介意使用from itertools import groupby digit_sum = lambda x: sum(int(i) for i in str(x)) [list(g) for _, g in groupby(sorted(range(1,26), key = digit_sum), key = digit_sum)] # ^^^^^^^^^^ replace this with your actual data # [[1, 10], # [2, 11, 20], # [3, 12, 21], # [4, 13, 22], # [5, 14, 23], # [6, 15, 24], # [7, 16, 25], # [8, 17], # [9, 18], # [19]] ,这是一种更有效的方法。

sorted()

它在这里的工作方式:使用groupby()按整数的数字总和对原始列表进行排序,这样您就可以使用dict_ = dict((k,list(g)) for k, g in groupby(sorted(range(1,26), key = digit_sum), key = digit_sum)) dict_ # {1: [1, 10], # 2: [2, 11, 20], # 3: [3, 12, 21], # 4: [4, 13, 22], # 5: [5, 14, 23], # 6: [6, 15, 24], # 7: [7, 16, 25], # 8: [8, 17], # 9: [9, 18], # 10: [19]} [dict_.get(key, []) for key in range(max(dict_.keys()))] # [[], # [1, 10], # [2, 11, 20], # [3, 12, 21], # [4, 13, 22], # [5, 14, 23], # [6, 15, 24], # [7, 16, 25], # [8, 17], # [9, 18]] 方法按数字总和对列表进行分组,然后循环组并将每个组中的整数转换为列表。

更新: 要获取子列表的数字总和等于索引的列表,您可以首先创建字典:

library(tidyverse)
mydf <- data_frame( treatment = c('ctrl','low','high','ctrl','low','high'), 
                gender = c('male','male','male','female','female','female'),
                size = c(10,20,30,10,20,30),
                result = c(0.11, 0.32, 0.25, 0.15, 0.38, 0.55) )

treatment  gender   size results
 ctrl       male     10    0.11
 low        male     20    0.32
 high       male     30    0.25
 ctrl       female   10    0.15
 low        female   20    0.35
 high       female   30    0.55

答案 1 :(得分:2)

以下在数据上只循环一次并返回一个字典,其键是和,而值是与该总和相对应的项:

from collections import defaultdict
from pprint import pprint

def group_by_sum(lst):
    d = defaultdict(list)
    for i in lst:
        d[sum(int(j) for j in str(i))].append(i)
    return d

pprint(group_by_sum(range(1, 25)))
# {1: [1, 10],
#  2: [2, 11, 20],
#  3: [3, 12, 21],
#  4: [4, 13, 22],
#  5: [5, 14, 23],
#  6: [6, 15, 24],
#  7: [7, 16],
#  8: [8, 17],
#  9: [9, 18],
#  10: [19]}

您可以根据总和对字典值进行排序以获得列表,但我认为将数据保存为字典可能会更好地为您服务。

答案 2 :(得分:0)

如果你想要一个留空列表的解决方案,并且空间效率不是你主要考虑的问题,我会使用一个元组列表:

>>> def digit_sum(digits):
...   total = 0
...   while digits != 0:
...     total += digits % 10
...     digits = digits // 10
...   return total
... 
>>> numbers = list(range(1,26))
>>> pairs = sorted((digit_sum(n),n) for n in numbers)
>>> pairs
[(1, 1), (1, 10), (2, 2), (2, 11), (2, 20), (3, 3), (3, 12), (3, 21), (4, 4), (4, 13), (4, 22), (5, 5), (5, 14), (5, 23), (6, 6), (6, 15), (6, 24), (7, 7), (7, 16), (7, 25), (8, 8), (8, 17), (9, 9), (9, 18), (10, 19)]
>>> maximum_sum = pairs[-1][0]
>>> list_of_lists = [[] for _ in range(maximum_sum+1)]
>>> for pair in pairs:
...   list_of_lists[pair[0]].append(pair[1])
... 
>>> list_of_lists
[[], [1, 10], [2, 11, 20], [3, 12, 21], [4, 13, 22], [5, 14, 23], [6, 15, 24], [7, 16, 25], [8, 17], [9, 18], [19]]
>>> 

因此,假设您的数据更加稀疏:

>>> numbers = [4,25,47,89]
>>> pairs = sorted((digit_sum(n),n) for n in numbers)
>>> pairs
[(4, 4), (7, 25), (11, 47), (17, 89)]
>>> maximum_sum = pairs[-1][0]
>>> list_of_lists = [[] for _ in range(maximum_sum+1)]
>>> for pair in pairs:
...   list_of_lists[pair[0]].append(pair[1])
... 
>>> from pprint import pprint
>>> pprint(list_of_lists,width=2)
[[],
 [],
 [],
 [],
 [4],
 [],
 [],
 [25],
 [],
 [],
 [],
 [47],
 [],
 [],
 [],
 [],
 [],
 [89]]
>>> 

您可以这样访问您的数据:

>>> list_of_lists[17]
[89]
>>> list_of_lists[8]
[]
>>> 

答案 3 :(得分:0)

非常简单:

list_of_lists = [[] for i in range(11)]

for i in range(25):
    digit_sum = sum(int(i) for i in str(i))
    list_of_lists[digit_sum].append(i)

print (list_of_lists)