1

I looked around and I can't seem to find the proper way of sorting a 32 entry tuple by inverting every odd and even entry.

ex:

1 0 3 2 5 4 7 6 9 8
to
0 1 2 3 4 5 6 7 8 9

My current code looks like this

i=0
nd = []
while i < len(self.r.ipDeviceName):
  print(i)
    if i%2:
      nd[i]=self.r.ipDeviceName[i-1]
    else:
      nd[i]=self.r.ipDeviceName[i+1]
dn = "".join(map(chr,nd))
devicenameText.SetValue(dn)

the type of self.r.ipDeviceName is tuple and I either get a IndexError or a tuple doesn't suport assignation depending on variations of the code

I also tried this with the same results

nd = self.r.ipDeviceName
for i in nd:
    if i&0x01:
        nd[i]=self.r.ipDeviceName[i-1]
    else:
        nd[i]=self.r.ipDeviceName[i+1]
dn = "".join(map(chr,nd))
devicenameText.SetValue(dn)

With the same results. Something very simple seems to elude me. Thanks for your help and time.

1
  • 1
    in your first code sample i is never in-/decremented and in your second code i would be a value not an index. Commented Jan 14, 2011 at 21:15

3 Answers 3

3

Tuples are immutable - you can't modify them once they are created. To modify individual elements you want to store the data in a mutable collection such as a list instead. You can use the built-in functions list and tuple to convert from tuple to list or vice versa.

Alternatively you could use zip and a functional style approach to create a new tuple from your existing tuple without modifying the original:

>>> t = tuple(range(10))
>>> tuple(x for i in zip(t[1::2], t[::2]) for x in i)
(1, 0, 3, 2, 5, 4, 7, 6, 9, 8)

Or using itertools.chain:

>>> import itertools
>>> tuple(itertools.chain(*zip(t[1::2], t[::2])))
(1, 0, 3, 2, 5, 4, 7, 6, 9, 8)

Note that the use of zip here assumes that your tuple has an even number of elements (which is the case here, according to your question).

Sign up to request clarification or add additional context in comments.

1 Comment

I missed something quite obvious it seems. I did not know about zip and intertools. Thanks
0

You can't change a tuple, they're immutable. However you can replace them with a new one arranged the way you want (I wouldn't call what you want "sorted"). To do it, all that is needed it to swap each pair of items that are in the original tuple.

Here's a straight-forward implementation. Note it leaves the last entry alone if there are an odd number of them since you never said how you wanted that case handled. Dealing with that possibility complicates the code slightly.

def swap_even_odd_entries(seq):
    tmp = list(seq)+[seq[-1]]  # convert sequence to mutable list and dup last
    for i in xrange(0, len(seq), 2):
        tmp[i],tmp[i+1] = tmp[i+1],tmp[i]  # swap each entry with following one
    return tuple(tmp[:len(seq)])  # remove any excess

a = (1, 0, 3, 2, 5, 4, 7, 6, 9, 8)
a = swap_even_odd_entries(a)
b = (91, 70, 23, 42, 75, 14, 87, 36, 19, 80)
b = swap_even_odd_entries(b)
c = (1, 0, 3, 2, 5)
c = swap_even_odd_entries(c)
print a
print b
print c
# output
#  (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
#  (70, 91, 42, 23, 14, 75, 36, 87, 80, 19)
#  (0, 1, 2, 3, 5)

The same thing can also be done in a less-readable way as a long single expression. Again the last entry remains unchanged if the length is odd.

swap_even_odd_entries2 = lambda t: tuple(
    v for p in [(b,a) for a,b in zip(*[iter(t)]*2) + [(t[-1],)*2]]
        for v in p)[:len(t)]

a = (1, 0, 3, 2, 5, 4, 7, 6, 9, 8)
a = swap_even_odd_entries2(a)
b = (91, 70, 23, 42, 75, 14, 87, 36, 19, 80)
b = swap_even_odd_entries2(b)
c = (1, 0, 3, 2, 5)
c = swap_even_odd_entries2(c)
print
print a
print b
print c
# output
#  (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
#  (70, 91, 42, 23, 14, 75, 36, 87, 80, 19)
#  (0, 1, 2, 3, 5)

1 Comment

This is exactly what I needed to understand. Thanks you.
0

If you add the functions grouper and flatten (see itertools recipes) to your toolset, you can do:

xs = [1, 0, 3, 2, 5, 4, 7, 6, 9, 8]
xs2 = flatten((y, x) for (x, y) in grouper(2, xs))
# list(xs2) => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

You could even write flatten(imap(reversed, grouper(2, xs)) but I guess only die-hard functional guys would like it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.