1

I'm struggling to find a pythonic way to move things from one list to another.

Eg.

list_of_things = [1, 2, 3, 4]

is_odd = lambda x: x % 2 != 0
odd_list = some_pythonic_operation(list_of_things, is_odd)

assert list_of_things == [2, 4]
assert odd_list == [1, 3]

Note: Please do not hyperfocus on the even/odd example and give a solution that handles just that case well, I'm looking for a general solution to this problem.

Note: I care very much about the performance and making sure this can be done in one pass, ideally in a readable pythonic way.

Alex Kyriazis
  • 311
  • 1
  • 4
  • 11
  • What about list comprehension? `[l for l in list_of_things if l % 2 != 0]` – Nechoj Nov 26 '21 at 19:19
  • 2
    Please edit the code of your best attempt into your question. – DisappointedByUnaccountableMod Nov 26 '21 at 19:24
  • 1
    @Nechoj Doesn't modify the original list. – Kelly Bundy Nov 26 '21 at 19:27
  • Is this a requirement to modify the original list? – Nechoj Nov 26 '21 at 19:32
  • Maybe `filter(is_odd, things)`? Not sure about orig. list (`req`?) – Daniel Hao Nov 26 '21 at 19:33
  • 3
    Related, and may actually answer the whole question: https://stackoverflow.com/questions/949098/split-a-list-based-on-a-condition – Gassa Nov 26 '21 at 19:34
  • `odds,list_of_things[:]=map(list,(zip(*zip((x for x in list_of_things if x%2),(y for y in list_of_things if not y%2)))))` – dawg Nov 26 '21 at 19:35
  • @Nechoj Yes it is. Look at the asserts again. – Kelly Bundy Nov 26 '21 at 19:36
  • 2
    About modifying the original list. The _performant_ way to modify the original list is to create another list by appending, and then assign it to the original list variable. Removing items from the middle is not performant. – Gassa Nov 26 '21 at 19:39
  • 1
    @Gassa [Directly writing each value into the original list](https://tio.run/##tZLPbsMgDMbveQpfpkKHqqbVpClSnySKIto4HVIgCOiU7eUzIP@WtpcdlhPYP3/2h6O/3Eerju/a9H1tWglOSBQOhNStceMtSSqsATtn@MWVbVXZlKibPKOxNEvAfyEGJ8iLeBP@uI@nujXQgVAw4gMdmdonXuCwRCadHdcaVUU6OqewsbgGR71cFL5Xt0oJeD1BGkMVNguZDcMZdDejYqdHX4cnvhjgJ6rBHpss/pux2OuOnCxkwWwEHp3UN3UJM662xNbmPOXHLsPYhqsrkuNo09loLy9gBqLe4vVXUbqny8ghF1DmNQLyLTSJpSFg6dOl@VaNsI5McrDdwhulK9R5aPj5SMPlueJZbDOvh8Hmetmh4ucGCd2wUfuU3snMT@lo8qd5tRHKESkUcZbCFlI8sli5K0vFJZblIDhwtO9/AA) seems performant as well, and likely saves memory. – Kelly Bundy Nov 26 '21 at 20:10

1 Answers1

-3

Your best bet might be to enumerate over the original list, popping things off it as you go.

list_of_things = [1, 2, 3, 4]
odd_list = [list_of_things.pop(i) for i, num in enumerate(list_of_things) if num % 2]

assert list_of_things == [2, 4]
assert odd_list == [1, 3]

Be warned: you are asking about a "Pythonic" way to do this. The Pythonic way is to create one list from another without touching the first list. The reason is mutating a collection as you iterate over it has lots of pitfalls you have to be worried about.

user1717828
  • 7,122
  • 8
  • 34
  • 59