Welcome, guest | Sign In | My Account | Store | Cart

This function accepts a sequence and a template of how the sequence should be reshaped.

Python, 58 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
def reshape(seq, how):
    """Reshape the sequence according to the template in ``how``.

    Examples
    ========

    >>> from sympy.utilities import reshape
    >>> seq = range(1, 9)

    >>> reshape(seq, [4]) # lists of 4
    [[1, 2, 3, 4], [5, 6, 7, 8]]

    >>> reshape(seq, (4,)) # tuples of 4
    [(1, 2, 3, 4), (5, 6, 7, 8)]

    >>> reshape(seq, (2, 2)) # tuples of 4
    [(1, 2, 3, 4), (5, 6, 7, 8)]

    >>> reshape(seq, (2, [2])) # (i, i, [i, i])
    [(1, 2, [3, 4]), (5, 6, [7, 8])]

    >>> reshape(seq, ((2,), [2])) # etc....
    [((1, 2), [3, 4]), ((5, 6), [7, 8])]

    >>> reshape(seq, (1, [2], 1))
    [(1, [2, 3], 4), (5, [6, 7], 8)]

    >>> reshape(tuple(seq), ([[1], 1, (2,)],))
    (([[1], 2, (3, 4)],), ([[5], 6, (7, 8)],))

    >>> reshape(tuple(seq), ([1], 1, (2,)))
    (([1], 2, (3, 4)), ([5], 6, (7, 8)))

    >>> reshape(range(12), [2, [3, set([2])], (1, (3,), 1)])
    [[0, 1, [2, 3, 4, set([5, 6])], (7, (8, 9, 10), 11)]]

    """
    m = sum(flatten(how))
    n, rem = divmod(len(seq), m)
    if m < 0 or rem:
        raise ValueError('template must sum to positive number '
        'that divides the length of the sequence')
    i = 0
    how_type = type(how)
    rv = [None]*n
    for k in range(len(rv)):
        rv[k] = []
        for hi in how:
            if type(hi) is int:
                rv[k].extend(seq[i: i + hi])
                i += hi
            else:
                n = sum(flatten(hi))
                hi_type = type(hi)
                rv[k].append(hi_type(reshape(seq[i: i + n], hi)[0]))
                i += n
        rv[k] = how_type(rv[k])
    return type(seq)(rv)

This is makes data entry convenient when dealing with nested tuples. e.g. if a routine requires a list of range/ value tuples -- range = (1, 3); value = 4. You can enter the flat data and reshape it into the range/value tuples:

reshape([1, 2, 3, 4, 5, 6], [(2,),1]) -> [[(1, 2), 3], [(4, 5), 6]]

The returned container will be the same as the type of the first argument and inside will be 1 or more repeated iterable that have the structure of the second argument.

5 comments

douglarek 11 years, 7 months ago  # | flag

cool

Warren Thom 11 years, 6 months ago  # | flag

Nice. But, I think you want 'how' for 'g' in line 34 and a bracket around 1,2,3,4,5,6 in the sample you gave. I have a use for the code. Thanks.

Chris Smith (author) 11 years, 6 months ago  # | flag

Thanks! It looks like you are correct. I'm not sure how to edit this but your comments indicate clearly what needs to change so I won't change anything for now.

Chris Smith (author) 11 years, 6 months ago  # | flag

OK, I see how to edit this, so I made the changes and added another example involving a set that indicated a problem in the code.

Michel Caillat 9 years, 3 months ago  # | flag

Chris, thank you very much for this contribution !

Created by Chris Smith on Fri, 14 Sep 2012 (MIT)
Python recipes (4591)
Chris Smith's recipes (3)

Required Modules

  • (none specified)

Other Information and Tasks