How to store some elements from a list into another

Jussi Piitulainen jussi.piitulainen at helsinki.fi
Tue Jun 13 03:48:53 EDT 2017


breamoreboy at gmail.com writes:

> On Monday, June 12, 2017 at 7:33:03 PM UTC+1, José Manuel Suárez Sierra wrote:
>> Hello,
>> I am stuck with a (perhaps) easy problem, I hope someone can help me:
>> 
>> My problem is:
>> I have a list of lists like this one:
>> [[55, 56, 57, 58, 83, 84, 85, 86, 89, 90, 91, 92, 107, 108, 109, 110,
>> 111, 117, 118, 119, 120, 128, 129, 130, 131, 135, 136, 137, 138, 184,
>> 185, 186, 187, 216, 217, 218, 219, 232, 233, 234, 235, 236, 237, 238,
>> 267, 268, 269, 270, 272, 273, 274, 275], [2, 3, 4, 5, 9, 10, 11, 12,
>> 21, 22, 23, 24, 29, 30, 31, 32, 56, 57, 58, 59, 65, 66, 67, 68, 74,
>> 75, 76, 77, 78, 89, 90, 91, 92, 98, 99, 100, 101, 102, 125, 126, 127,
>> 128, 131, 132, 133, 134, 135]]
>> 
>> And what I want is to store some of these datum into another list
>> according to the next conditions:
>>
>> 1. I just want to store data if these values are consecutive (four in
>> four), for instance, for first element I would like to store into the
>> new list: [[[55,58],[83,86],....[n,n+3]]] and so on.
>>
>>  I tried something like this:
>> 
>>         x=0
>>         y=0
>>         while list6[x][y] == list6[x][y+1]-1 and list6[x][y] == list6[x][y+1]-2 and list6[x][y] == list6[x][y+1]-3 or list6[x][0]:
>> 
>>             list7.append(list6[x][y])
>>             list7.append(list6[x][y+3])
>>             y = y+1
>>             if (list6[x][y])%(list6[x][len(list6[x])-1]) == 0:
>>                 x= x+1
>> 
>>             if len(list6[x]) == x and len(list6[x][y]) == y:
>>                 break
>> 
>> 
>> It does not work
>> 
>> I appreciate your help 
>> Thank you
>
> Perhaps use the recipe for consecutive numbers from here
> https://docs.python.org/2.6/library/itertools.html#examples It will
> have to be modified for Python 3, I'll leave that as an exercise.

What a clever idea. Pity it's gone in newer documentation. (By the "it"
in the previous sentence I refer only to the idea of grouping by the
difference to the index in the original sequence, and by "gone" only to
the fact that I didn't see this example at the corresponding location
for Python 3.6, which I found by replacing the 2 in the URL with 3.
Perhaps the idea is preserved somewhere else?)

Anyway, I've adapted it to Python 3, and to an analysis of the problem
at hand - mainly the problem that the OP finds themselves _stuck_ with
their spec and their code, as quoted above. Hope it helps.

What follows, follows.

# The big idea is to define (auxiliary) functions. It's not an
# advanced idea. It's the most basic of all ideas. The experience of
# being stuck comes from trying to see the whole problem at once.

# Ok, familiary with standard ways of viewing things helps. But that
# is just the flip side of breaking problems into manageable parts:
# past experience suggests that some kinds of parts are more useful,
# more composable into a solution, so in standard libraries.

# One subproblem is to group just one list of numbers, then it is easy
# to group every list in a list of such lists. But another subproblem
# is to deal with one group of numbers. There seem to be two concerns:
# a group should consist of consecutive numbers, and a group should
# consist of four numbers - the latter at least is easy enough if the
# group is stored as a list, but what should be done if there are five
# or seven numbers? No idea, but that can be clarified later once the
# components of a solution are untangled into their own functions.

# The battle cry is: Use def!

import itertools as it
import operator as op

def applied(f):
    '''Reification of that asterisk - like a really advanced
    computer-sciency kind of thing. But see no lambda!'''
    def F(args): return f(*args)
    return F

def consequences(data):
    '''Lists of consecutive datami, clever idea adapted from
    https://docs.python.org/2.6/library/itertools.html#examples'''
    for k, group in it.groupby(enumerate(data), applied(op.sub)):
        yield [datum for index, datum in group]

def isfourlong(sequence):
    '''True if sequence is of length 4.'''
    return len(sequence) == 4

def ends(sequences):
    '''Collect the endpoints of sequences in a list of 2-lists.'''
    return [[sequence[0], sequence[-1]] for sequence in sequences]

data = [[55, 56, 57, 58, 83, 84, 85, 86, 89, 90, 91, 92, 107, 108,
         109, 110, 111, 117, 118, 119, 120, 128, 129, 130, 131, 135,
         136, 137, 138, 184, 185, 186, 187, 216, 217, 218, 219, 232,
         233, 234, 235, 236, 237, 238, 267, 268, 269, 270, 272, 273,
         274, 275],
        
        [2, 3, 4, 5, 9, 10, 11, 12, 21, 22, 23, 24, 29, 30, 31, 32,
         56, 57, 58, 59, 65, 66, 67, 68, 74, 75, 76, 77, 78, 89, 90,
         91, 92, 98, 99, 100, 101, 102, 125, 126, 127, 128, 131, 132,
         133, 134, 135]]

def testrun():
    '''See how many variations can be composed out of the few auxiliary
    functions - the problem becomes tame, or at least a bit tamer.
    This kind of ad-hoc test suite is very useful, during development,
    when at all in doubt.'''
    print('groups in both lists:')
    print(list(consequences(data[0])))
    print(list(consequences(data[1])))
    # note the calls to list() - consequences() returns an opaque
    # generator object that can be drained into a list when needed;
    # filter objects below are similarly opaque and drainable - define
    # an auxiliary that returns a list instead if that feels scary -
    # Don't Panic!
    print()
    print('groups of four in both lists:')
    print(list(filter(isfourlong, consequences(data[0]))))
    print(list(filter(isfourlong, consequences(data[1]))))
    print()
    print('ends of all groups in both lists:')
    print(ends(consequences(data[0])))
    print(ends(consequences(data[1])))
    print()
    print('ends of groups of four in both lists:')
    print(ends(filter(isfourlong, consequences(data[0]))))
    print(ends(filter(isfourlong, consequences(data[1]))))
    print()
    print('lists of ends of all groups:')
    print([ends(consequences(datami)) for datami in data])
    print()
    print('lists of ends of groups of four:')
    print([ends(filter(isfourlong, consequences(datami)))
           for datami in data])

if __name__ == '__main__':
    # inside the above condition, these commands are executed when the
    # script is executed but not when it is imported as a library, so
    # it is easy to run the test from the shell and easy to import the
    # definitions into an interactive session
    testrun()



More information about the Python-list mailing list