Pythonic way to iterate over two lists?

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Pythonic way to iterate over two lists?

Casey Callendrello
Hi there,
I've got a simple problem that I've already solved effectively, but I
can't help thinking that there must be a more "pythonic" way to do it.
Especially because my solution uses a list index, which I *know* can't
possibly be the Python way ;-).

In any case, I have two lists: one of machines, and one of jobs. Either
one can be of arbitrary length, including zero. I want to generate
(machine, job) pairs where every machine gets at most one job, each job
is only executed once, and as much work as possible is done. The actual
index or order is irrelevant.

The simple, C-inspired solution is:

i = 0
while i<len(jobs) and i<len(machines):
     do_job(jobs[i], machines[i])
     i += 1

There has to be a cleaner way than that! Any suggestions?

--Casey



_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies
Reply | Threaded
Open this post in threaded view
|

Re: Pythonic way to iterate over two lists?

Casey Callendrello
I should add, I'm actually more interested in a list of (job, machine)
tuples, since that's added to a queue and sent to a threadpool.

--Casey

On 6/6/11 9:32 PM, Casey Callendrello wrote:

> Hi there,
> I've got a simple problem that I've already solved effectively, but I
> can't help thinking that there must be a more "pythonic" way to do it.
> Especially because my solution uses a list index, which I *know* can't
> possibly be the Python way ;-).
>
> In any case, I have two lists: one of machines, and one of jobs.
> Either one can be of arbitrary length, including zero. I want to
> generate (machine, job) pairs where every machine gets at most one
> job, each job is only executed once, and as much work as possible is
> done. The actual index or order is irrelevant.
>
> The simple, C-inspired solution is:
>
> i = 0
> while i<len(jobs) and i<len(machines):
>     do_job(jobs[i], machines[i])
>     i += 1
>
> There has to be a cleaner way than that! Any suggestions?
>
> --Casey
>
>
>
> _______________________________________________
> Baypiggies mailing list
> [hidden email]
> To change your subscription options or unsubscribe:
> http://mail.python.org/mailman/listinfo/baypiggies

_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies
Reply | Threaded
Open this post in threaded view
|

Re: Pythonic way to iterate over two lists?

Ross Patterson-2
In reply to this post by Casey Callendrello
I suspect you could use itertools.izip_longest:


Ross

On Mon, Jun 6, 2011 at 9:32 PM, Casey Callendrello <[hidden email]> wrote:
Hi there,
I've got a simple problem that I've already solved effectively, but I can't help thinking that there must be a more "pythonic" way to do it. Especially because my solution uses a list index, which I *know* can't possibly be the Python way ;-).

In any case, I have two lists: one of machines, and one of jobs. Either one can be of arbitrary length, including zero. I want to generate (machine, job) pairs where every machine gets at most one job, each job is only executed once, and as much work as possible is done. The actual index or order is irrelevant.

The simple, C-inspired solution is:

i = 0
while i<len(jobs) and i<len(machines):
   do_job(jobs[i], machines[i])
   i += 1

There has to be a cleaner way than that! Any suggestions?

--Casey



_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies


_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies
Reply | Threaded
Open this post in threaded view
|

Re: Pythonic way to iterate over two lists?

Hy Carrinski
The following will work.
Does it fully solve your problem?

from itertools import izip

for (job, machine) in izip(jobs, machines):
    do_job(job, machine)

On Mon, Jun 6, 2011 at 9:37 PM, Ross Patterson <[hidden email]> wrote:

> I suspect you could use itertools.izip_longest:
> http://docs.python.org/library/itertools.html#itertools.izip_longest
> Ross
> On Mon, Jun 6, 2011 at 9:32 PM, Casey Callendrello <[hidden email]> wrote:
>>
>> Hi there,
>> I've got a simple problem that I've already solved effectively, but I
>> can't help thinking that there must be a more "pythonic" way to do it.
>> Especially because my solution uses a list index, which I *know* can't
>> possibly be the Python way ;-).
>>
>> In any case, I have two lists: one of machines, and one of jobs. Either
>> one can be of arbitrary length, including zero. I want to generate (machine,
>> job) pairs where every machine gets at most one job, each job is only
>> executed once, and as much work as possible is done. The actual index or
>> order is irrelevant.
>>
>> The simple, C-inspired solution is:
>>
>> i = 0
>> while i<len(jobs) and i<len(machines):
>>    do_job(jobs[i], machines[i])
>>    i += 1
>>
>> There has to be a cleaner way than that! Any suggestions?
>>
>> --Casey
>>
>>
>>
>> _______________________________________________
>> Baypiggies mailing list
>> [hidden email]
>> To change your subscription options or unsubscribe:
>> http://mail.python.org/mailman/listinfo/baypiggies
>
>
> _______________________________________________
> Baypiggies mailing list
> [hidden email]
> To change your subscription options or unsubscribe:
> http://mail.python.org/mailman/listinfo/baypiggies
>
_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies
Reply | Threaded
Open this post in threaded view
|

Re: Pythonic way to iterate over two lists?

Max Slimmer
In reply to this post by Casey Callendrello
A more realistic and in some ways interesting problem is to deal with
potentially more jobs than machines. I would think that you want all
the jobs to get done therefore any one machine might need to do more
than one job, Then for fun some machines are might be more efficient,
in either time or cost.  :-)

max



On Mon, Jun 6, 2011 at 9:32 PM, Casey Callendrello <[hidden email]> wrote:

> Hi there,
> I've got a simple problem that I've already solved effectively, but I can't
> help thinking that there must be a more "pythonic" way to do it. Especially
> because my solution uses a list index, which I *know* can't possibly be the
> Python way ;-).
>
> In any case, I have two lists: one of machines, and one of jobs. Either one
> can be of arbitrary length, including zero. I want to generate (machine,
> job) pairs where every machine gets at most one job, each job is only
> executed once, and as much work as possible is done. The actual index or
> order is irrelevant.
>
> The simple, C-inspired solution is:
>
> i = 0
> while i<len(jobs) and i<len(machines):
>    do_job(jobs[i], machines[i])
>    i += 1
>
> There has to be a cleaner way than that! Any suggestions?
>
> --Casey
>
>
>
> _______________________________________________
> Baypiggies mailing list
> [hidden email]
> To change your subscription options or unsubscribe:
> http://mail.python.org/mailman/listinfo/baypiggies
>
_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies
Reply | Threaded
Open this post in threaded view
|

Re: Pythonic way to iterate over two lists?

Jeremy Fishman
In reply to this post by Hy Carrinski
More information:

izip() is the iterative version of the core Python builtin zip(), which returns a list.

In Python 3+ zip() returns an iterable object (it's a type)

Cheers,
Jeremy

On Mon, Jun 6, 2011 at 9:44 PM, Hy Carrinski <[hidden email]> wrote:
The following will work.
Does it fully solve your problem?

from itertools import izip

for (job, machine) in izip(jobs, machines):
   do_job(job, machine)

On Mon, Jun 6, 2011 at 9:37 PM, Ross Patterson <[hidden email]> wrote:
> I suspect you could use itertools.izip_longest:
> http://docs.python.org/library/itertools.html#itertools.izip_longest
> Ross
> On Mon, Jun 6, 2011 at 9:32 PM, Casey Callendrello <[hidden email]> wrote:
>>
>> Hi there,
>> I've got a simple problem that I've already solved effectively, but I
>> can't help thinking that there must be a more "pythonic" way to do it.
>> Especially because my solution uses a list index, which I *know* can't
>> possibly be the Python way ;-).
>>
>> In any case, I have two lists: one of machines, and one of jobs. Either
>> one can be of arbitrary length, including zero. I want to generate (machine,
>> job) pairs where every machine gets at most one job, each job is only
>> executed once, and as much work as possible is done. The actual index or
>> order is irrelevant.
>>
>> The simple, C-inspired solution is:
>>
>> i = 0
>> while i<len(jobs) and i<len(machines):
>>    do_job(jobs[i], machines[i])
>>    i += 1
>>
>> There has to be a cleaner way than that! Any suggestions?
>>
>> --Casey
>>
>>
>>
>> _______________________________________________
>> Baypiggies mailing list
>> [hidden email]
>> To change your subscription options or unsubscribe:
>> http://mail.python.org/mailman/listinfo/baypiggies
>
>
> _______________________________________________
> Baypiggies mailing list
> [hidden email]
> To change your subscription options or unsubscribe:
> http://mail.python.org/mailman/listinfo/baypiggies
>
_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies


_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies
Reply | Threaded
Open this post in threaded view
|

Re: Pythonic way to iterate over two lists?

Simeon Franklin
I taught a Python Fundamentals class last week for Marakana and
noticed that other programmers coming from languages that are not
specifically functionally oriented were unfamiliar with zip as a
concept. Most explanations of zip tend to focus on the two case (given
two lists it returns paired elements) and the more general Python
documentation explanation was met with thoughtful incomprehension:

>This function returns a list of tuples, where the i-th tuple contains the i-th element from each of the argument sequences or iterables.

When I paraphrased this as "zip will take arguments that represent
rows of input data and return a list whose elements are the columns of
the input data" mental lightbulbs went on all over the room. YMMV but
I thought it made for an intuitive explanation... It also leads me to
think more naturally of possible applications of zip and iterative
friends.

-regards
Simeon Franklin
_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies
Reply | Threaded
Open this post in threaded view
|

Re: Pythonic way to iterate over two lists?

Mark Voorhies
On Monday, June 06, 2011 10:43:41 pm Simeon Franklin wrote:

> I taught a Python Fundamentals class last week for Marakana and
> noticed that other programmers coming from languages that are not
> specifically functionally oriented were unfamiliar with zip as a
> concept. Most explanations of zip tend to focus on the two case (given
> two lists it returns paired elements) and the more general Python
> documentation explanation was met with thoughtful incomprehension:
>
> >This function returns a list of tuples, where the i-th tuple contains the i-th element from each of the argument sequences or iterables.
>
> When I paraphrased this as "zip will take arguments that represent
> rows of input data and return a list whose elements are the columns of
> the input data" mental lightbulbs went on all over the room. YMMV but
> I thought it made for an intuitive explanation... It also leads me to
> think more naturally of possible applications of zip and iterative
> friends.

Yes!
transpose_A = zip(*A)
# if A is, e.g., a rectangular matrix as a list of lists

Thanks for the very useful point of view =)

--Mark

>
> -regards
> Simeon Franklin
> _______________________________________________
> Baypiggies mailing list
> [hidden email]
> To change your subscription options or unsubscribe:
> http://mail.python.org/mailman/listinfo/baypiggies
>
_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies