ᴘᴀɴᴀʏɪᴏᴛɪs
ᴘᴀɴᴀʏɪᴏᴛɪs

Reputation: 7529

Python map with list as input

I'm trying to construct permutations of a list with the i-th bit flipped every time.

For example:

With input:

[1,0,0,0]

To get:

[0,0,0,0]

[1,1,0,0]

[1,0,1,0]

[1,0,0,1]

I wrote a method which given a list returns the same list with the bit at position p changed:

def flipBit(l,p):
    l[p] = ~l[p]&1
    return l

And I'm trying to apply it using a map(), but I can't even get a basic example working:

p=list(map(flipBit, [[1,0,0]]*3,range(3))))

This is what it returns:

[[0, 1, 1], [0, 1, 1], [0, 1, 1]]

while expecting:

[[0, 0, 0], [1, 1, 0], [1, 0, 1]]

What I'm I doing wrong? (if anyone can suggest an even shorter code for this maybe without using a flipbit method I'd appreciate it as I won't really use flipbit other than this purpose and I want to keep the code concise and clean)

Upvotes: 1

Views: 122

Answers (2)

NPE
NPE

Reputation: 500893

The issue is that [[1,0,0]]*3 creates a list containing three references to the same sublist. When you change one sublist, they all change.

Here is one way to fix this:

>>> list(map(flipBit, [[1,0,0] for _ in range(3)], range(3)))
                      ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
[[0, 0, 0], [1, 1, 0], [1, 0, 1]]

And here is a way to implement this functionality without using a helper function:

>>> l = [1, 0, 0]
>>> [l[:i] + [1-l[i]] + l[i+1:] for i in range(len(l))]
[[0, 0, 0], [1, 1, 0], [1, 0, 1]]

Upvotes: 1

dmg
dmg

Reputation: 7716

The code you posted is was not valid at all, but I presume you need this:

>>> p=list(map(lambda x: flipBit([1, 0, 0], x), range(3)))
>>> p
[[0, 0, 0], [1, 1, 0], [1, 0, 1]]

Basically, you map with a lambda function, that partially applies [1, 0, 0] as l, and then takes each element in range(3) and applies it to p.

Upvotes: 1

Related Questions