0

I would like to divide a list of positive integers by the length of digits.
For example, int_list = [1,3,13,888,1004] -> [1,3] , [13] , [888] , [1004]

I have implemented below:

def seperate_by_digit(int_list):
    len_set = set()  # track how many digits we have

    int_dict = {}  # key : len of digits  / val : list of integer
    for int_ele in int_list:
        n = len(str(int_ele))
        if n not in len_set:
            int_dict[n] = [int_ele]
            len_set.add(n)
        else:
            sub_int_list = int_dict[n]
            sub_int_list.append(int_ele)
            int_dict[n] = sub_int_list
    return int_dict

Is there any better, cleaner way to complete this task?

S.B
  • 13,077
  • 10
  • 22
  • 49
user715519
  • 63
  • 1
  • 5

5 Answers5

0

To get the length of the digits, it simpler to use the string representation.

Assuming you don't have negative numbers, one solution is to first sort your list, then groupby the list based on length.

from itertools import groupby


def split_list(lst):
    return [list(g) for _, g in
            groupby(sorted(lst), key=lambda x: len(str(x)))]


lst = [1, 3, 13, 888, 1004]

print(split_list(lst))

output:

[[1, 3], [13], [888], [1004]]
S.B
  • 13,077
  • 10
  • 22
  • 49
0

Here's a quick implementation using a defaultdict.

from collections import defaultdict as dd

def separate_by_digit(int_list):
    int_dict = dd(list)
    for k in int_list:
        int_dict[len(str(k))].append(k)
    return int_dict

print(list(separate_by_digit([1,3,13,888,1004]).values()))

Result:

[[1, 3], [13], [888], [1004]]
Ben Grossmann
  • 4,387
  • 1
  • 12
  • 16
0

Based on this linke converting to str have performance issue, we can do it as:

import math


def getIntegerPlaces(theNumber):
    if theNumber <= 999999999999997:
        return int(math.log10(theNumber)) + 1
    else:
        counter = 15
        while theNumber >= 10**counter:
            counter += 1
        return counter

def convert(l):
    m = {}
    for v in a:
        digitCount = getIntegerPlaces(v)
        if not digitCount in m:
            m[digitCount] = []
        m[digitCount].append(v)
    return list(m.values())

a = [1,3,13,888,1004]
print(convert(a))

The output will be:

[[1, 3], [13], [888], [1004]]
S4eed3sm
  • 1,398
  • 5
  • 20
0

It's multiple passes, but a way to accomplish this would be to create a set of the lengths of the numbers in lst.

lst = [1, 3, 13, 888, 1004]

lens = set(len(str(x)) for x in lst)

We can then iterate over this set and filter lst for each length.

grouped = [[x for x in lst if len(str(x)) == l] for l in lens]

End result:

[[1, 3], [13], [888], [1004]]
Chris
  • 26,361
  • 5
  • 21
  • 42
0

You could use a defaultdict to manage the grouping and length of the string value to get the number of digits:

from math import log
from collections import defaultdict

int_list = [1,3,13,888,1004]

int_dict = defaultdict(list)
for n in int_list:
    int_dict[len(str(n))].append(n)
    
print(*int_dict.values())
# [1, 3] [13] [888] [1004]
Alain T.
  • 40,517
  • 4
  • 31
  • 51