Better method to iterate over 3 lists

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
6
down vote

favorite
1












I am creating a program which iterates over the width and height of an image as well as makes use of a set of keys.



Here is an example:



width = [0,1,2,3,4,6,7,8,9]
height = [0,1,2,3,4]
keys = [18,20,11]


The width and height are a range of integers up to the size of the width and height.
The keys are any set of numbers (actually ASCII values) but are not ordered numbers.



I would like the output to be like this:



0 0 18
0 1 20
0 2 11
0 3 18
0 4 20
1 0 11
1 1 18
. . ..
9 0 20
9 1 11
9 2 18
9 3 20
9 4 11


As you can see, the width and height can be produced with nested for loops, whereas the keys cycle between each other.



Here is my solution:



w = [0,1,2,3,4,6,7,8,9]
h = [0,1,2,3,4]
k = [18,20,11]

kIndex = 0

for i in w:
for j in h:
print(i,j,k[kIndex])
# Cycle through the keys index.
# The modulo is used to return to the beginning of the keys list
kIndex = (kIndex + 1) % len(k)


Actually it works as intended, however, I would like a more efficient way to do the above instead of using an incremental variable for the index position of the keys list.



I don't mind the nested for loop, if that has to be used, but the index keys variable annoys me as it seems like the code won't work without it, but at the same time isn't really pythonic.










share|improve this question

























    up vote
    6
    down vote

    favorite
    1












    I am creating a program which iterates over the width and height of an image as well as makes use of a set of keys.



    Here is an example:



    width = [0,1,2,3,4,6,7,8,9]
    height = [0,1,2,3,4]
    keys = [18,20,11]


    The width and height are a range of integers up to the size of the width and height.
    The keys are any set of numbers (actually ASCII values) but are not ordered numbers.



    I would like the output to be like this:



    0 0 18
    0 1 20
    0 2 11
    0 3 18
    0 4 20
    1 0 11
    1 1 18
    . . ..
    9 0 20
    9 1 11
    9 2 18
    9 3 20
    9 4 11


    As you can see, the width and height can be produced with nested for loops, whereas the keys cycle between each other.



    Here is my solution:



    w = [0,1,2,3,4,6,7,8,9]
    h = [0,1,2,3,4]
    k = [18,20,11]

    kIndex = 0

    for i in w:
    for j in h:
    print(i,j,k[kIndex])
    # Cycle through the keys index.
    # The modulo is used to return to the beginning of the keys list
    kIndex = (kIndex + 1) % len(k)


    Actually it works as intended, however, I would like a more efficient way to do the above instead of using an incremental variable for the index position of the keys list.



    I don't mind the nested for loop, if that has to be used, but the index keys variable annoys me as it seems like the code won't work without it, but at the same time isn't really pythonic.










    share|improve this question























      up vote
      6
      down vote

      favorite
      1









      up vote
      6
      down vote

      favorite
      1






      1





      I am creating a program which iterates over the width and height of an image as well as makes use of a set of keys.



      Here is an example:



      width = [0,1,2,3,4,6,7,8,9]
      height = [0,1,2,3,4]
      keys = [18,20,11]


      The width and height are a range of integers up to the size of the width and height.
      The keys are any set of numbers (actually ASCII values) but are not ordered numbers.



      I would like the output to be like this:



      0 0 18
      0 1 20
      0 2 11
      0 3 18
      0 4 20
      1 0 11
      1 1 18
      . . ..
      9 0 20
      9 1 11
      9 2 18
      9 3 20
      9 4 11


      As you can see, the width and height can be produced with nested for loops, whereas the keys cycle between each other.



      Here is my solution:



      w = [0,1,2,3,4,6,7,8,9]
      h = [0,1,2,3,4]
      k = [18,20,11]

      kIndex = 0

      for i in w:
      for j in h:
      print(i,j,k[kIndex])
      # Cycle through the keys index.
      # The modulo is used to return to the beginning of the keys list
      kIndex = (kIndex + 1) % len(k)


      Actually it works as intended, however, I would like a more efficient way to do the above instead of using an incremental variable for the index position of the keys list.



      I don't mind the nested for loop, if that has to be used, but the index keys variable annoys me as it seems like the code won't work without it, but at the same time isn't really pythonic.










      share|improve this question













      I am creating a program which iterates over the width and height of an image as well as makes use of a set of keys.



      Here is an example:



      width = [0,1,2,3,4,6,7,8,9]
      height = [0,1,2,3,4]
      keys = [18,20,11]


      The width and height are a range of integers up to the size of the width and height.
      The keys are any set of numbers (actually ASCII values) but are not ordered numbers.



      I would like the output to be like this:



      0 0 18
      0 1 20
      0 2 11
      0 3 18
      0 4 20
      1 0 11
      1 1 18
      . . ..
      9 0 20
      9 1 11
      9 2 18
      9 3 20
      9 4 11


      As you can see, the width and height can be produced with nested for loops, whereas the keys cycle between each other.



      Here is my solution:



      w = [0,1,2,3,4,6,7,8,9]
      h = [0,1,2,3,4]
      k = [18,20,11]

      kIndex = 0

      for i in w:
      for j in h:
      print(i,j,k[kIndex])
      # Cycle through the keys index.
      # The modulo is used to return to the beginning of the keys list
      kIndex = (kIndex + 1) % len(k)


      Actually it works as intended, however, I would like a more efficient way to do the above instead of using an incremental variable for the index position of the keys list.



      I don't mind the nested for loop, if that has to be used, but the index keys variable annoys me as it seems like the code won't work without it, but at the same time isn't really pythonic.







      python






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 4 hours ago









      Suraj Kothari

      300112




      300112






















          3 Answers
          3






          active

          oldest

          votes

















          up vote
          9
          down vote



          accepted










          You can use itertools.product to get the product of you width and height. You then want to cycle over the keys, thus use itertools.cycle. You then zip those together and get the desired result.



          Finally, you can make this a generator using yield for memory efficieny.



          from itertools import product, cycle

          def get_grid(width, height, keys):
          for pos, key in zip(product(width, height), cycle(keys)):
          yield (*pos, key)


          Or if you do not want a generator.



          out = [(*pos, key) for pos, key in zip(product(width, height), cycle(keys))]


          Example



          width = [0,1,2,3,4,6,7,8,9]
          height = [0,1,2,3,4]
          keys = [18,20,11]

          for triple in get_grid(width, height, keys):
          print(triple)


          Output



          (0, 0, 18)
          (0, 1, 20)
          (0, 2, 11)
          (0, 3, 18)
          (0, 4, 20)
          (1, 0, 11)
          (1, 1, 18)
          ...


          As a sidenote, notice that you could replace the lists defining width and height by ranges.



          width = range(10)
          height = range(5)





          share|improve this answer


















          • 1




            Pretty much what I was about to post: [(w,h,k) for (w,h),k in zip(product(width, height), cycle(keys))]
            – tobias_k
            4 hours ago










          • Is there a way without a generator. I'm not too confident with them. The itertools library seems ok, but the generator seems off my level.
            – Suraj Kothari
            3 hours ago










          • @SurajKothari Yes, you can simply cast the generator to a list by doing list(get_grid(width, height, keys)).
            – Olivier Melançon
            3 hours ago






          • 1




            I have used width = range(Image.size[0]), but to understand my problem I used my example with an arbitrary list
            – Suraj Kothari
            3 hours ago






          • 1




            Thanks for the list comprehension. I seem to understand it slightly better since I use them all the time. However, it has dawned on me that the generator version is more "beautiful" or elegant and I might consider them anyways. Thanks a lot.
            – Suraj Kothari
            3 hours ago

















          up vote
          1
          down vote













          You can use cycle from itertools.



          from itertools import cycle, product

          width = [0,1,2,3,4,6,7,8,9]
          height = [0,1,2,3,4]
          keys = [18,20,11]


          c = cycle(keys)

          for w,h in product(width,height):
          print(w,h,next(c))





          share|improve this answer





























            up vote
            0
            down vote













            You can use iterate over matrix. Its ndenumerate function from numpy packet. If width and height are range of int, you can skip creating list. Just define the size of this lists.



            width = 10
            height = 5
            k = [18,20,11]

            kIndex = 0

            for (i,j), value in np.ndenumerate(np.ones((height,width))):
            print(i,j,k[kIndex])
            # Cycle through the keys index.
            # The modulo is used to return to the beginning of the keys list
            kIndex = (kIndex + 1) % len(k)





            share|improve this answer




















              Your Answer





              StackExchange.ifUsing("editor", function ()
              StackExchange.using("externalEditor", function ()
              StackExchange.using("snippets", function ()
              StackExchange.snippets.init();
              );
              );
              , "code-snippets");

              StackExchange.ready(function()
              var channelOptions =
              tags: "".split(" "),
              id: "1"
              ;
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function()
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled)
              StackExchange.using("snippets", function()
              createEditor();
              );

              else
              createEditor();

              );

              function createEditor()
              StackExchange.prepareEditor(
              heartbeatType: 'answer',
              convertImagesToLinks: true,
              noModals: false,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              );



              );













               

              draft saved


              draft discarded


















              StackExchange.ready(
              function ()
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52804895%2fbetter-method-to-iterate-over-3-lists%23new-answer', 'question_page');

              );

              Post as a guest






























              3 Answers
              3






              active

              oldest

              votes








              3 Answers
              3






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              9
              down vote



              accepted










              You can use itertools.product to get the product of you width and height. You then want to cycle over the keys, thus use itertools.cycle. You then zip those together and get the desired result.



              Finally, you can make this a generator using yield for memory efficieny.



              from itertools import product, cycle

              def get_grid(width, height, keys):
              for pos, key in zip(product(width, height), cycle(keys)):
              yield (*pos, key)


              Or if you do not want a generator.



              out = [(*pos, key) for pos, key in zip(product(width, height), cycle(keys))]


              Example



              width = [0,1,2,3,4,6,7,8,9]
              height = [0,1,2,3,4]
              keys = [18,20,11]

              for triple in get_grid(width, height, keys):
              print(triple)


              Output



              (0, 0, 18)
              (0, 1, 20)
              (0, 2, 11)
              (0, 3, 18)
              (0, 4, 20)
              (1, 0, 11)
              (1, 1, 18)
              ...


              As a sidenote, notice that you could replace the lists defining width and height by ranges.



              width = range(10)
              height = range(5)





              share|improve this answer


















              • 1




                Pretty much what I was about to post: [(w,h,k) for (w,h),k in zip(product(width, height), cycle(keys))]
                – tobias_k
                4 hours ago










              • Is there a way without a generator. I'm not too confident with them. The itertools library seems ok, but the generator seems off my level.
                – Suraj Kothari
                3 hours ago










              • @SurajKothari Yes, you can simply cast the generator to a list by doing list(get_grid(width, height, keys)).
                – Olivier Melançon
                3 hours ago






              • 1




                I have used width = range(Image.size[0]), but to understand my problem I used my example with an arbitrary list
                – Suraj Kothari
                3 hours ago






              • 1




                Thanks for the list comprehension. I seem to understand it slightly better since I use them all the time. However, it has dawned on me that the generator version is more "beautiful" or elegant and I might consider them anyways. Thanks a lot.
                – Suraj Kothari
                3 hours ago














              up vote
              9
              down vote



              accepted










              You can use itertools.product to get the product of you width and height. You then want to cycle over the keys, thus use itertools.cycle. You then zip those together and get the desired result.



              Finally, you can make this a generator using yield for memory efficieny.



              from itertools import product, cycle

              def get_grid(width, height, keys):
              for pos, key in zip(product(width, height), cycle(keys)):
              yield (*pos, key)


              Or if you do not want a generator.



              out = [(*pos, key) for pos, key in zip(product(width, height), cycle(keys))]


              Example



              width = [0,1,2,3,4,6,7,8,9]
              height = [0,1,2,3,4]
              keys = [18,20,11]

              for triple in get_grid(width, height, keys):
              print(triple)


              Output



              (0, 0, 18)
              (0, 1, 20)
              (0, 2, 11)
              (0, 3, 18)
              (0, 4, 20)
              (1, 0, 11)
              (1, 1, 18)
              ...


              As a sidenote, notice that you could replace the lists defining width and height by ranges.



              width = range(10)
              height = range(5)





              share|improve this answer


















              • 1




                Pretty much what I was about to post: [(w,h,k) for (w,h),k in zip(product(width, height), cycle(keys))]
                – tobias_k
                4 hours ago










              • Is there a way without a generator. I'm not too confident with them. The itertools library seems ok, but the generator seems off my level.
                – Suraj Kothari
                3 hours ago










              • @SurajKothari Yes, you can simply cast the generator to a list by doing list(get_grid(width, height, keys)).
                – Olivier Melançon
                3 hours ago






              • 1




                I have used width = range(Image.size[0]), but to understand my problem I used my example with an arbitrary list
                – Suraj Kothari
                3 hours ago






              • 1




                Thanks for the list comprehension. I seem to understand it slightly better since I use them all the time. However, it has dawned on me that the generator version is more "beautiful" or elegant and I might consider them anyways. Thanks a lot.
                – Suraj Kothari
                3 hours ago












              up vote
              9
              down vote



              accepted







              up vote
              9
              down vote



              accepted






              You can use itertools.product to get the product of you width and height. You then want to cycle over the keys, thus use itertools.cycle. You then zip those together and get the desired result.



              Finally, you can make this a generator using yield for memory efficieny.



              from itertools import product, cycle

              def get_grid(width, height, keys):
              for pos, key in zip(product(width, height), cycle(keys)):
              yield (*pos, key)


              Or if you do not want a generator.



              out = [(*pos, key) for pos, key in zip(product(width, height), cycle(keys))]


              Example



              width = [0,1,2,3,4,6,7,8,9]
              height = [0,1,2,3,4]
              keys = [18,20,11]

              for triple in get_grid(width, height, keys):
              print(triple)


              Output



              (0, 0, 18)
              (0, 1, 20)
              (0, 2, 11)
              (0, 3, 18)
              (0, 4, 20)
              (1, 0, 11)
              (1, 1, 18)
              ...


              As a sidenote, notice that you could replace the lists defining width and height by ranges.



              width = range(10)
              height = range(5)





              share|improve this answer














              You can use itertools.product to get the product of you width and height. You then want to cycle over the keys, thus use itertools.cycle. You then zip those together and get the desired result.



              Finally, you can make this a generator using yield for memory efficieny.



              from itertools import product, cycle

              def get_grid(width, height, keys):
              for pos, key in zip(product(width, height), cycle(keys)):
              yield (*pos, key)


              Or if you do not want a generator.



              out = [(*pos, key) for pos, key in zip(product(width, height), cycle(keys))]


              Example



              width = [0,1,2,3,4,6,7,8,9]
              height = [0,1,2,3,4]
              keys = [18,20,11]

              for triple in get_grid(width, height, keys):
              print(triple)


              Output



              (0, 0, 18)
              (0, 1, 20)
              (0, 2, 11)
              (0, 3, 18)
              (0, 4, 20)
              (1, 0, 11)
              (1, 1, 18)
              ...


              As a sidenote, notice that you could replace the lists defining width and height by ranges.



              width = range(10)
              height = range(5)






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited 3 hours ago

























              answered 4 hours ago









              Olivier Melançon

              12.3k11636




              12.3k11636







              • 1




                Pretty much what I was about to post: [(w,h,k) for (w,h),k in zip(product(width, height), cycle(keys))]
                – tobias_k
                4 hours ago










              • Is there a way without a generator. I'm not too confident with them. The itertools library seems ok, but the generator seems off my level.
                – Suraj Kothari
                3 hours ago










              • @SurajKothari Yes, you can simply cast the generator to a list by doing list(get_grid(width, height, keys)).
                – Olivier Melançon
                3 hours ago






              • 1




                I have used width = range(Image.size[0]), but to understand my problem I used my example with an arbitrary list
                – Suraj Kothari
                3 hours ago






              • 1




                Thanks for the list comprehension. I seem to understand it slightly better since I use them all the time. However, it has dawned on me that the generator version is more "beautiful" or elegant and I might consider them anyways. Thanks a lot.
                – Suraj Kothari
                3 hours ago












              • 1




                Pretty much what I was about to post: [(w,h,k) for (w,h),k in zip(product(width, height), cycle(keys))]
                – tobias_k
                4 hours ago










              • Is there a way without a generator. I'm not too confident with them. The itertools library seems ok, but the generator seems off my level.
                – Suraj Kothari
                3 hours ago










              • @SurajKothari Yes, you can simply cast the generator to a list by doing list(get_grid(width, height, keys)).
                – Olivier Melançon
                3 hours ago






              • 1




                I have used width = range(Image.size[0]), but to understand my problem I used my example with an arbitrary list
                – Suraj Kothari
                3 hours ago






              • 1




                Thanks for the list comprehension. I seem to understand it slightly better since I use them all the time. However, it has dawned on me that the generator version is more "beautiful" or elegant and I might consider them anyways. Thanks a lot.
                – Suraj Kothari
                3 hours ago







              1




              1




              Pretty much what I was about to post: [(w,h,k) for (w,h),k in zip(product(width, height), cycle(keys))]
              – tobias_k
              4 hours ago




              Pretty much what I was about to post: [(w,h,k) for (w,h),k in zip(product(width, height), cycle(keys))]
              – tobias_k
              4 hours ago












              Is there a way without a generator. I'm not too confident with them. The itertools library seems ok, but the generator seems off my level.
              – Suraj Kothari
              3 hours ago




              Is there a way without a generator. I'm not too confident with them. The itertools library seems ok, but the generator seems off my level.
              – Suraj Kothari
              3 hours ago












              @SurajKothari Yes, you can simply cast the generator to a list by doing list(get_grid(width, height, keys)).
              – Olivier Melançon
              3 hours ago




              @SurajKothari Yes, you can simply cast the generator to a list by doing list(get_grid(width, height, keys)).
              – Olivier Melançon
              3 hours ago




              1




              1




              I have used width = range(Image.size[0]), but to understand my problem I used my example with an arbitrary list
              – Suraj Kothari
              3 hours ago




              I have used width = range(Image.size[0]), but to understand my problem I used my example with an arbitrary list
              – Suraj Kothari
              3 hours ago




              1




              1




              Thanks for the list comprehension. I seem to understand it slightly better since I use them all the time. However, it has dawned on me that the generator version is more "beautiful" or elegant and I might consider them anyways. Thanks a lot.
              – Suraj Kothari
              3 hours ago




              Thanks for the list comprehension. I seem to understand it slightly better since I use them all the time. However, it has dawned on me that the generator version is more "beautiful" or elegant and I might consider them anyways. Thanks a lot.
              – Suraj Kothari
              3 hours ago












              up vote
              1
              down vote













              You can use cycle from itertools.



              from itertools import cycle, product

              width = [0,1,2,3,4,6,7,8,9]
              height = [0,1,2,3,4]
              keys = [18,20,11]


              c = cycle(keys)

              for w,h in product(width,height):
              print(w,h,next(c))





              share|improve this answer


























                up vote
                1
                down vote













                You can use cycle from itertools.



                from itertools import cycle, product

                width = [0,1,2,3,4,6,7,8,9]
                height = [0,1,2,3,4]
                keys = [18,20,11]


                c = cycle(keys)

                for w,h in product(width,height):
                print(w,h,next(c))





                share|improve this answer
























                  up vote
                  1
                  down vote










                  up vote
                  1
                  down vote









                  You can use cycle from itertools.



                  from itertools import cycle, product

                  width = [0,1,2,3,4,6,7,8,9]
                  height = [0,1,2,3,4]
                  keys = [18,20,11]


                  c = cycle(keys)

                  for w,h in product(width,height):
                  print(w,h,next(c))





                  share|improve this answer














                  You can use cycle from itertools.



                  from itertools import cycle, product

                  width = [0,1,2,3,4,6,7,8,9]
                  height = [0,1,2,3,4]
                  keys = [18,20,11]


                  c = cycle(keys)

                  for w,h in product(width,height):
                  print(w,h,next(c))






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 3 hours ago

























                  answered 3 hours ago









                  Christian Sloper

                  6817




                  6817




















                      up vote
                      0
                      down vote













                      You can use iterate over matrix. Its ndenumerate function from numpy packet. If width and height are range of int, you can skip creating list. Just define the size of this lists.



                      width = 10
                      height = 5
                      k = [18,20,11]

                      kIndex = 0

                      for (i,j), value in np.ndenumerate(np.ones((height,width))):
                      print(i,j,k[kIndex])
                      # Cycle through the keys index.
                      # The modulo is used to return to the beginning of the keys list
                      kIndex = (kIndex + 1) % len(k)





                      share|improve this answer
























                        up vote
                        0
                        down vote













                        You can use iterate over matrix. Its ndenumerate function from numpy packet. If width and height are range of int, you can skip creating list. Just define the size of this lists.



                        width = 10
                        height = 5
                        k = [18,20,11]

                        kIndex = 0

                        for (i,j), value in np.ndenumerate(np.ones((height,width))):
                        print(i,j,k[kIndex])
                        # Cycle through the keys index.
                        # The modulo is used to return to the beginning of the keys list
                        kIndex = (kIndex + 1) % len(k)





                        share|improve this answer






















                          up vote
                          0
                          down vote










                          up vote
                          0
                          down vote









                          You can use iterate over matrix. Its ndenumerate function from numpy packet. If width and height are range of int, you can skip creating list. Just define the size of this lists.



                          width = 10
                          height = 5
                          k = [18,20,11]

                          kIndex = 0

                          for (i,j), value in np.ndenumerate(np.ones((height,width))):
                          print(i,j,k[kIndex])
                          # Cycle through the keys index.
                          # The modulo is used to return to the beginning of the keys list
                          kIndex = (kIndex + 1) % len(k)





                          share|improve this answer












                          You can use iterate over matrix. Its ndenumerate function from numpy packet. If width and height are range of int, you can skip creating list. Just define the size of this lists.



                          width = 10
                          height = 5
                          k = [18,20,11]

                          kIndex = 0

                          for (i,j), value in np.ndenumerate(np.ones((height,width))):
                          print(i,j,k[kIndex])
                          # Cycle through the keys index.
                          # The modulo is used to return to the beginning of the keys list
                          kIndex = (kIndex + 1) % len(k)






                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered 3 hours ago









                          Cezary.Sz

                          587414




                          587414



























                               

                              draft saved


                              draft discarded















































                               


                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function ()
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52804895%2fbetter-method-to-iterate-over-3-lists%23new-answer', 'question_page');

                              );

                              Post as a guest













































































                              Comments

                              Popular posts from this blog

                              Long meetings (6-7 hours a day): Being “babysat” by supervisor

                              Is the Concept of Multiple Fantasy Races Scientifically Flawed? [closed]

                              Confectionery