Symmetric set difference using set (list) comprehension not giving expected result









up vote
2
down vote

favorite












I'm learning python and would like to understand what is happening here. I'm sure I'm missing something basic. I'm getting elements from two lists that do not show up in both. Here is my code with output:



 l = [1, 8, 3, 4]
m = [4, 6, 3, 8]

Method 1:
r = list(set(l) - set(m)) + list(set(m) - set(l))
[1, 6]

Method 2:
print [(x,y) for x in l for y in m if x not in m and y not in l]
[(1, 6)]

Method 3 (same but returns a list):
print [[x,y] for x in l for y in m if x not in m and y not in l]
[[1, 6]]


I would like a list comprehension that would return the same list as returned by method 1.



Also, as far as I understand I'm getting a generator as a result of the code in list comprehension. However, I cannot turn it into a simple list:



 res = ((x,y) for x in l for y in m if x not in m and y not in l)
print list(res)
[(1, 6)]


Why is that? I'm expecting:



 [1, 6]


EDIT: my main question is: why can't I turn generator from my list comprehension above into a list? According to the accepted answer in this question using list(res) should work. I want to understand why it doesn't.










share|improve this question



























    up vote
    2
    down vote

    favorite












    I'm learning python and would like to understand what is happening here. I'm sure I'm missing something basic. I'm getting elements from two lists that do not show up in both. Here is my code with output:



     l = [1, 8, 3, 4]
    m = [4, 6, 3, 8]

    Method 1:
    r = list(set(l) - set(m)) + list(set(m) - set(l))
    [1, 6]

    Method 2:
    print [(x,y) for x in l for y in m if x not in m and y not in l]
    [(1, 6)]

    Method 3 (same but returns a list):
    print [[x,y] for x in l for y in m if x not in m and y not in l]
    [[1, 6]]


    I would like a list comprehension that would return the same list as returned by method 1.



    Also, as far as I understand I'm getting a generator as a result of the code in list comprehension. However, I cannot turn it into a simple list:



     res = ((x,y) for x in l for y in m if x not in m and y not in l)
    print list(res)
    [(1, 6)]


    Why is that? I'm expecting:



     [1, 6]


    EDIT: my main question is: why can't I turn generator from my list comprehension above into a list? According to the accepted answer in this question using list(res) should work. I want to understand why it doesn't.










    share|improve this question

























      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      I'm learning python and would like to understand what is happening here. I'm sure I'm missing something basic. I'm getting elements from two lists that do not show up in both. Here is my code with output:



       l = [1, 8, 3, 4]
      m = [4, 6, 3, 8]

      Method 1:
      r = list(set(l) - set(m)) + list(set(m) - set(l))
      [1, 6]

      Method 2:
      print [(x,y) for x in l for y in m if x not in m and y not in l]
      [(1, 6)]

      Method 3 (same but returns a list):
      print [[x,y] for x in l for y in m if x not in m and y not in l]
      [[1, 6]]


      I would like a list comprehension that would return the same list as returned by method 1.



      Also, as far as I understand I'm getting a generator as a result of the code in list comprehension. However, I cannot turn it into a simple list:



       res = ((x,y) for x in l for y in m if x not in m and y not in l)
      print list(res)
      [(1, 6)]


      Why is that? I'm expecting:



       [1, 6]


      EDIT: my main question is: why can't I turn generator from my list comprehension above into a list? According to the accepted answer in this question using list(res) should work. I want to understand why it doesn't.










      share|improve this question















      I'm learning python and would like to understand what is happening here. I'm sure I'm missing something basic. I'm getting elements from two lists that do not show up in both. Here is my code with output:



       l = [1, 8, 3, 4]
      m = [4, 6, 3, 8]

      Method 1:
      r = list(set(l) - set(m)) + list(set(m) - set(l))
      [1, 6]

      Method 2:
      print [(x,y) for x in l for y in m if x not in m and y not in l]
      [(1, 6)]

      Method 3 (same but returns a list):
      print [[x,y] for x in l for y in m if x not in m and y not in l]
      [[1, 6]]


      I would like a list comprehension that would return the same list as returned by method 1.



      Also, as far as I understand I'm getting a generator as a result of the code in list comprehension. However, I cannot turn it into a simple list:



       res = ((x,y) for x in l for y in m if x not in m and y not in l)
      print list(res)
      [(1, 6)]


      Why is that? I'm expecting:



       [1, 6]


      EDIT: my main question is: why can't I turn generator from my list comprehension above into a list? According to the accepted answer in this question using list(res) should work. I want to understand why it doesn't.







      python set list-comprehension






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 10 at 4:08









      coldspeed

      111k17101170




      111k17101170










      asked Nov 9 at 3:35









      Lidia

      64721226




      64721226






















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          2
          down vote



          accepted










          list(set(l) - set(m)) + list(set(m) - set(l)) is a windy way of finding the symmetric difference between two sets ("the set of elements which are in either of the sets and not in their intersection"—Wikipedia).



          >>> set(l).symmetric_difference(m)
          1, 6



          Anyway, with a list comprehension, this is how I'd do it:



          >>> el for (this,other) in [(m,l),(l,m)] for el in this if el not in other
          1, 6


          Which is the same as



          >>> symdif = set()
          >>> for this,other in [(m,l),(l,m)]:
          ... for el in this:
          ... if el not in other:
          ... symdif.add(el)
          ...
          >>> symdif
          1, 6


          ...not that I'd recommend it.






          share|improve this answer


















          • 1




            @U9-Forward That's the symmetric difference. The reason I didn't do it is because I didn't want to convert both l AND m into a set to compute it. With the symmetric_difference, I don't have to convert both, just one.
            – coldspeed
            Nov 9 at 3:43










          • Oh, That's true, alright i deleted my comment.
            – U9-Forward
            Nov 9 at 3:44










          • @coldspeed: Note: symmetric_difference converts to set under the hood in the current implementation on CPython, so you end up with the temporary set no matter what you do.
            – ShadowRanger
            Nov 9 at 3:51










          • @ShadowRanger True, but the function does it for me.... might be just me but I find the function call cleaner... must be my pandas background. :-)
            – coldspeed
            Nov 9 at 3:52










          • This is what I'm getting as output from symmetric_difference: set([1, 6]) I'm confused, is it a set containing a list of two elements? I'm on python 2.7, if that makes a difference.
            – Lidia
            Nov 10 at 2:54


















          up vote
          1
          down vote













          It's because your converting the generator to a list!



          So it's gonna be equivalent to a list comprehension!!!



          Also another option is:



          list(set(l)^set(m))


          Very short and good.






          share|improve this answer
















          • 1




            Note: list(set(l)^set(m)) doesn't preserve the partial ordering based on set of origin that list(set(l) - set(m)) + list(set(m) - set(l)) does, so it might not be appropriate, but if the ordering isn't important, yeah, it's clearly the best solution.
            – ShadowRanger
            Nov 9 at 3:48











          • @ShadowRanger that's right, thank you :-)
            – U9-Forward
            Nov 9 at 3:49










          • This is a great solution (without preserving order), however, I still don't understand why I can't convert output of my list comprehension to a simple list. This was my question. The accepted answer in this question says you can get a list from generator by doing list(gen), so why isn't it working with my generator?
            – Lidia
            Nov 10 at 3:05










          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: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          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%2f53219488%2fsymmetric-set-difference-using-set-list-comprehension-not-giving-expected-resu%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          2
          down vote



          accepted










          list(set(l) - set(m)) + list(set(m) - set(l)) is a windy way of finding the symmetric difference between two sets ("the set of elements which are in either of the sets and not in their intersection"—Wikipedia).



          >>> set(l).symmetric_difference(m)
          1, 6



          Anyway, with a list comprehension, this is how I'd do it:



          >>> el for (this,other) in [(m,l),(l,m)] for el in this if el not in other
          1, 6


          Which is the same as



          >>> symdif = set()
          >>> for this,other in [(m,l),(l,m)]:
          ... for el in this:
          ... if el not in other:
          ... symdif.add(el)
          ...
          >>> symdif
          1, 6


          ...not that I'd recommend it.






          share|improve this answer


















          • 1




            @U9-Forward That's the symmetric difference. The reason I didn't do it is because I didn't want to convert both l AND m into a set to compute it. With the symmetric_difference, I don't have to convert both, just one.
            – coldspeed
            Nov 9 at 3:43










          • Oh, That's true, alright i deleted my comment.
            – U9-Forward
            Nov 9 at 3:44










          • @coldspeed: Note: symmetric_difference converts to set under the hood in the current implementation on CPython, so you end up with the temporary set no matter what you do.
            – ShadowRanger
            Nov 9 at 3:51










          • @ShadowRanger True, but the function does it for me.... might be just me but I find the function call cleaner... must be my pandas background. :-)
            – coldspeed
            Nov 9 at 3:52










          • This is what I'm getting as output from symmetric_difference: set([1, 6]) I'm confused, is it a set containing a list of two elements? I'm on python 2.7, if that makes a difference.
            – Lidia
            Nov 10 at 2:54















          up vote
          2
          down vote



          accepted










          list(set(l) - set(m)) + list(set(m) - set(l)) is a windy way of finding the symmetric difference between two sets ("the set of elements which are in either of the sets and not in their intersection"—Wikipedia).



          >>> set(l).symmetric_difference(m)
          1, 6



          Anyway, with a list comprehension, this is how I'd do it:



          >>> el for (this,other) in [(m,l),(l,m)] for el in this if el not in other
          1, 6


          Which is the same as



          >>> symdif = set()
          >>> for this,other in [(m,l),(l,m)]:
          ... for el in this:
          ... if el not in other:
          ... symdif.add(el)
          ...
          >>> symdif
          1, 6


          ...not that I'd recommend it.






          share|improve this answer


















          • 1




            @U9-Forward That's the symmetric difference. The reason I didn't do it is because I didn't want to convert both l AND m into a set to compute it. With the symmetric_difference, I don't have to convert both, just one.
            – coldspeed
            Nov 9 at 3:43










          • Oh, That's true, alright i deleted my comment.
            – U9-Forward
            Nov 9 at 3:44










          • @coldspeed: Note: symmetric_difference converts to set under the hood in the current implementation on CPython, so you end up with the temporary set no matter what you do.
            – ShadowRanger
            Nov 9 at 3:51










          • @ShadowRanger True, but the function does it for me.... might be just me but I find the function call cleaner... must be my pandas background. :-)
            – coldspeed
            Nov 9 at 3:52










          • This is what I'm getting as output from symmetric_difference: set([1, 6]) I'm confused, is it a set containing a list of two elements? I'm on python 2.7, if that makes a difference.
            – Lidia
            Nov 10 at 2:54













          up vote
          2
          down vote



          accepted







          up vote
          2
          down vote



          accepted






          list(set(l) - set(m)) + list(set(m) - set(l)) is a windy way of finding the symmetric difference between two sets ("the set of elements which are in either of the sets and not in their intersection"—Wikipedia).



          >>> set(l).symmetric_difference(m)
          1, 6



          Anyway, with a list comprehension, this is how I'd do it:



          >>> el for (this,other) in [(m,l),(l,m)] for el in this if el not in other
          1, 6


          Which is the same as



          >>> symdif = set()
          >>> for this,other in [(m,l),(l,m)]:
          ... for el in this:
          ... if el not in other:
          ... symdif.add(el)
          ...
          >>> symdif
          1, 6


          ...not that I'd recommend it.






          share|improve this answer














          list(set(l) - set(m)) + list(set(m) - set(l)) is a windy way of finding the symmetric difference between two sets ("the set of elements which are in either of the sets and not in their intersection"—Wikipedia).



          >>> set(l).symmetric_difference(m)
          1, 6



          Anyway, with a list comprehension, this is how I'd do it:



          >>> el for (this,other) in [(m,l),(l,m)] for el in this if el not in other
          1, 6


          Which is the same as



          >>> symdif = set()
          >>> for this,other in [(m,l),(l,m)]:
          ... for el in this:
          ... if el not in other:
          ... symdif.add(el)
          ...
          >>> symdif
          1, 6


          ...not that I'd recommend it.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 9 at 3:45

























          answered Nov 9 at 3:39









          coldspeed

          111k17101170




          111k17101170







          • 1




            @U9-Forward That's the symmetric difference. The reason I didn't do it is because I didn't want to convert both l AND m into a set to compute it. With the symmetric_difference, I don't have to convert both, just one.
            – coldspeed
            Nov 9 at 3:43










          • Oh, That's true, alright i deleted my comment.
            – U9-Forward
            Nov 9 at 3:44










          • @coldspeed: Note: symmetric_difference converts to set under the hood in the current implementation on CPython, so you end up with the temporary set no matter what you do.
            – ShadowRanger
            Nov 9 at 3:51










          • @ShadowRanger True, but the function does it for me.... might be just me but I find the function call cleaner... must be my pandas background. :-)
            – coldspeed
            Nov 9 at 3:52










          • This is what I'm getting as output from symmetric_difference: set([1, 6]) I'm confused, is it a set containing a list of two elements? I'm on python 2.7, if that makes a difference.
            – Lidia
            Nov 10 at 2:54













          • 1




            @U9-Forward That's the symmetric difference. The reason I didn't do it is because I didn't want to convert both l AND m into a set to compute it. With the symmetric_difference, I don't have to convert both, just one.
            – coldspeed
            Nov 9 at 3:43










          • Oh, That's true, alright i deleted my comment.
            – U9-Forward
            Nov 9 at 3:44










          • @coldspeed: Note: symmetric_difference converts to set under the hood in the current implementation on CPython, so you end up with the temporary set no matter what you do.
            – ShadowRanger
            Nov 9 at 3:51










          • @ShadowRanger True, but the function does it for me.... might be just me but I find the function call cleaner... must be my pandas background. :-)
            – coldspeed
            Nov 9 at 3:52










          • This is what I'm getting as output from symmetric_difference: set([1, 6]) I'm confused, is it a set containing a list of two elements? I'm on python 2.7, if that makes a difference.
            – Lidia
            Nov 10 at 2:54








          1




          1




          @U9-Forward That's the symmetric difference. The reason I didn't do it is because I didn't want to convert both l AND m into a set to compute it. With the symmetric_difference, I don't have to convert both, just one.
          – coldspeed
          Nov 9 at 3:43




          @U9-Forward That's the symmetric difference. The reason I didn't do it is because I didn't want to convert both l AND m into a set to compute it. With the symmetric_difference, I don't have to convert both, just one.
          – coldspeed
          Nov 9 at 3:43












          Oh, That's true, alright i deleted my comment.
          – U9-Forward
          Nov 9 at 3:44




          Oh, That's true, alright i deleted my comment.
          – U9-Forward
          Nov 9 at 3:44












          @coldspeed: Note: symmetric_difference converts to set under the hood in the current implementation on CPython, so you end up with the temporary set no matter what you do.
          – ShadowRanger
          Nov 9 at 3:51




          @coldspeed: Note: symmetric_difference converts to set under the hood in the current implementation on CPython, so you end up with the temporary set no matter what you do.
          – ShadowRanger
          Nov 9 at 3:51












          @ShadowRanger True, but the function does it for me.... might be just me but I find the function call cleaner... must be my pandas background. :-)
          – coldspeed
          Nov 9 at 3:52




          @ShadowRanger True, but the function does it for me.... might be just me but I find the function call cleaner... must be my pandas background. :-)
          – coldspeed
          Nov 9 at 3:52












          This is what I'm getting as output from symmetric_difference: set([1, 6]) I'm confused, is it a set containing a list of two elements? I'm on python 2.7, if that makes a difference.
          – Lidia
          Nov 10 at 2:54





          This is what I'm getting as output from symmetric_difference: set([1, 6]) I'm confused, is it a set containing a list of two elements? I'm on python 2.7, if that makes a difference.
          – Lidia
          Nov 10 at 2:54













          up vote
          1
          down vote













          It's because your converting the generator to a list!



          So it's gonna be equivalent to a list comprehension!!!



          Also another option is:



          list(set(l)^set(m))


          Very short and good.






          share|improve this answer
















          • 1




            Note: list(set(l)^set(m)) doesn't preserve the partial ordering based on set of origin that list(set(l) - set(m)) + list(set(m) - set(l)) does, so it might not be appropriate, but if the ordering isn't important, yeah, it's clearly the best solution.
            – ShadowRanger
            Nov 9 at 3:48











          • @ShadowRanger that's right, thank you :-)
            – U9-Forward
            Nov 9 at 3:49










          • This is a great solution (without preserving order), however, I still don't understand why I can't convert output of my list comprehension to a simple list. This was my question. The accepted answer in this question says you can get a list from generator by doing list(gen), so why isn't it working with my generator?
            – Lidia
            Nov 10 at 3:05














          up vote
          1
          down vote













          It's because your converting the generator to a list!



          So it's gonna be equivalent to a list comprehension!!!



          Also another option is:



          list(set(l)^set(m))


          Very short and good.






          share|improve this answer
















          • 1




            Note: list(set(l)^set(m)) doesn't preserve the partial ordering based on set of origin that list(set(l) - set(m)) + list(set(m) - set(l)) does, so it might not be appropriate, but if the ordering isn't important, yeah, it's clearly the best solution.
            – ShadowRanger
            Nov 9 at 3:48











          • @ShadowRanger that's right, thank you :-)
            – U9-Forward
            Nov 9 at 3:49










          • This is a great solution (without preserving order), however, I still don't understand why I can't convert output of my list comprehension to a simple list. This was my question. The accepted answer in this question says you can get a list from generator by doing list(gen), so why isn't it working with my generator?
            – Lidia
            Nov 10 at 3:05












          up vote
          1
          down vote










          up vote
          1
          down vote









          It's because your converting the generator to a list!



          So it's gonna be equivalent to a list comprehension!!!



          Also another option is:



          list(set(l)^set(m))


          Very short and good.






          share|improve this answer












          It's because your converting the generator to a list!



          So it's gonna be equivalent to a list comprehension!!!



          Also another option is:



          list(set(l)^set(m))


          Very short and good.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 9 at 3:41









          U9-Forward

          10.2k2834




          10.2k2834







          • 1




            Note: list(set(l)^set(m)) doesn't preserve the partial ordering based on set of origin that list(set(l) - set(m)) + list(set(m) - set(l)) does, so it might not be appropriate, but if the ordering isn't important, yeah, it's clearly the best solution.
            – ShadowRanger
            Nov 9 at 3:48











          • @ShadowRanger that's right, thank you :-)
            – U9-Forward
            Nov 9 at 3:49










          • This is a great solution (without preserving order), however, I still don't understand why I can't convert output of my list comprehension to a simple list. This was my question. The accepted answer in this question says you can get a list from generator by doing list(gen), so why isn't it working with my generator?
            – Lidia
            Nov 10 at 3:05












          • 1




            Note: list(set(l)^set(m)) doesn't preserve the partial ordering based on set of origin that list(set(l) - set(m)) + list(set(m) - set(l)) does, so it might not be appropriate, but if the ordering isn't important, yeah, it's clearly the best solution.
            – ShadowRanger
            Nov 9 at 3:48











          • @ShadowRanger that's right, thank you :-)
            – U9-Forward
            Nov 9 at 3:49










          • This is a great solution (without preserving order), however, I still don't understand why I can't convert output of my list comprehension to a simple list. This was my question. The accepted answer in this question says you can get a list from generator by doing list(gen), so why isn't it working with my generator?
            – Lidia
            Nov 10 at 3:05







          1




          1




          Note: list(set(l)^set(m)) doesn't preserve the partial ordering based on set of origin that list(set(l) - set(m)) + list(set(m) - set(l)) does, so it might not be appropriate, but if the ordering isn't important, yeah, it's clearly the best solution.
          – ShadowRanger
          Nov 9 at 3:48





          Note: list(set(l)^set(m)) doesn't preserve the partial ordering based on set of origin that list(set(l) - set(m)) + list(set(m) - set(l)) does, so it might not be appropriate, but if the ordering isn't important, yeah, it's clearly the best solution.
          – ShadowRanger
          Nov 9 at 3:48













          @ShadowRanger that's right, thank you :-)
          – U9-Forward
          Nov 9 at 3:49




          @ShadowRanger that's right, thank you :-)
          – U9-Forward
          Nov 9 at 3:49












          This is a great solution (without preserving order), however, I still don't understand why I can't convert output of my list comprehension to a simple list. This was my question. The accepted answer in this question says you can get a list from generator by doing list(gen), so why isn't it working with my generator?
          – Lidia
          Nov 10 at 3:05




          This is a great solution (without preserving order), however, I still don't understand why I can't convert output of my list comprehension to a simple list. This was my question. The accepted answer in this question says you can get a list from generator by doing list(gen), so why isn't it working with my generator?
          – Lidia
          Nov 10 at 3:05

















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53219488%2fsymmetric-set-difference-using-set-list-comprehension-not-giving-expected-resu%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Kleinkühnau

          Makov (Slowakei)

          Deutsches Schauspielhaus