0

So I have the following example of code; simultaneously iterates over multiple sequences combined with enumerate, assigning the values to tuple variable after which outputs it.

def PairValuesWithIndexToTuples(self,val1,val2):
  t =()
  for i, (a,b) in enumerate(zip(val1,val2)):
    t += (i,a,b)
  return t

What I want to achieve is something like this if it is possible: I have been searching around but I could not find yet a solution which achieves my results from the method written above:

def PairValuesWithIndexToTuples(self,val1,val2):
  t =()
  t += for i, (a,b) in enumerate(zip(val1,val2))
  return t

or

return t+= for i, (a,b) in enumerate(zip(val1,val2))
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
nclaudiuf
  • 91
  • 1
  • 5
  • 2
    **Never** ask for one-liner. Instead, ask for short and clean code. Otherwise you should use `exec('for i,(a,b) in enumerate(zip(val1,val2)):\nt+=(i,a,b);')`. – user202729 Jul 20 '18 at 16:19

4 Answers4

0

You can make a generator expression to create the tuples, then chain.from_iterable from that expression to get the flattened result

from itertools import chain

tuple(chain.from_iterable((i, a, b) for i, (a,b) in enumerate(zip(val1,val2))))

This looks much nicer as a multiline function

def pair_with_index(*its):
    e = enumerate(zip(*its))
    flattened = ((i, *t) for i, t in e)
    c = chain.from_iterable(flattened)
    return tuple(c)

pair_with_index([1, 2, 3], [4, 5, 6])
# (0, 1, 4, 1, 2, 5, 2, 3, 6)

Edit:

My original code (for a tuple of tuples) was

def pair_with_index(val1, val2):
    return tuple((i, a, b) for i, (a,b) in enumerate(zip(val1,val2)))

pair_with_index([1, 2, 3], [4, 5, 6])
# ((0, 1, 4), (1, 2, 5), (2, 3, 6))
Patrick Haugh
  • 59,226
  • 13
  • 88
  • 96
  • 4
    That's a different result - You have a tuple of tuples rather than a tuple of values. – FHTMitchell Jul 20 '18 at 16:22
  • @FHTMitchell Fixed. – Patrick Haugh Jul 20 '18 at 16:31
  • Thanks for the comment @PatrickHaugh. I was actually looking for obtaining a tuple of tuples but I wanted to know if i could rewrite my code in a more optimised way. So instead of having 5 lines of code I could only have 2 or 3. – nclaudiuf Jul 22 '18 at 22:12
  • Looking at my first code snipped I wanted to know if I can achieve something like: def PairValuesWithIndexToTuples(self,val1,val2): return t+= for i, (a,b) in enumerate(zip(val1,val2)) or def PairValuesWithIndexToTuples(self,val1,val2): t =() t += for i, (a,b) in enumerate(zip(val1,val2)) return t – nclaudiuf Jul 22 '18 at 22:13
  • @nclaudiuf Is the output of my edit more what you're looking for? The problem with posting examples with made-up syntax is that I'm not sure which result you're looking for. Could you provide sample inputs/outputs? – Patrick Haugh Jul 22 '18 at 22:17
  • Yes, the second comment, is exactly what I was looking for ! I am just new to python so i did not get it from your first post that I could do a return there. Thanks for the rewrite – nclaudiuf Jul 22 '18 at 22:24
  • I had voted your code up but, I do not have yet enough points to make a difference ... – nclaudiuf Jul 22 '18 at 22:27
  • You can also [accept answers](https://stackoverflow.com/help/someone-answers), but please don't feel pressured to unless it answers your question. – Patrick Haugh Jul 22 '18 at 22:29
0

Perhaps you're looking for a flattened list or a flattened tuple? Not clear from your question, so I'll just include everything.

In [79]: val1 = [1,2,3]

In [80]: val2=[4,5,6]

In [81]: [(i, a, b) for i, (a,b) in enumerate(zip(val1,val2))]
Out[81]: [(0, 1, 4), (1, 2, 5), (2, 3, 6)]

In [82]: [k for j in [(i, a, b) for i, (a,b) in enumerate(zip(val1,val2))] for k in j]
Out[82]: [0, 1, 4, 1, 2, 5, 2, 3, 6]

In [84]: tuple(k for j in [(i, a, b) for i, (a,b) in enumerate(zip(val1,val2))] for k in j)
Out[84]: (0, 1, 4, 1, 2, 5, 2, 3, 6)
Ashish Acharya
  • 3,349
  • 1
  • 16
  • 25
  • Thnaks for the comment @Acharya. Its good to know I can also achieve that. I was though looking to get a tuples of tuples return. But I just wanted to optimise my code in shorter amount of code possible. You can have a look at the comment I posted to Patrick – nclaudiuf Jul 22 '18 at 22:16
-2

Because this is so much clearer...

sum(((i, a, b) for i, (a,b) in enumerate(zip(val1, val2))), ())

example:

val1 = 'hello'

val2 = range(5)

sum(((i, a, b) for i, (a,b) in enumerate(zip(val1, val2))), ())
# -> (0, 'h', 0, 1, 'e', 1, 2, 'l', 2, 3, 'l', 3, 4, 'o', 4)
FHTMitchell
  • 11,793
  • 2
  • 35
  • 47
  • 2
    [Append on tuples forms a monoid too](https://stackoverflow.com/a/952946/5267751) – user202729 Jul 20 '18 at 16:25
  • `functools.reduce(lambda a,b: a+b, ((i, a, b) for i, (a,b) in enumerate(zip(val1, val2))))` is faster here -- I think `sum(x, [])` is O(n^2) – MoxieBall Jul 20 '18 at 16:27
  • @MoxieBall [Yes it is](https://stackoverflow.com/questions/952914/making-a-flat-list-out-of-list-of-lists-in-python#comment77806270_952946) – user202729 Jul 20 '18 at 16:27
  • I am wrong, functools.reduce is not faster. itertools.chain is the way to go. – MoxieBall Jul 20 '18 at 16:32
-2

While I don't advocate abusing sum, it is possible to do this in order to concatenate tuples together

sum(tuples, ())

Or in your case

sum(((i, a, b) for i, (a, b) in enumerate(zip(val1, val2))), ())

It is important to note that this can be inefficient, given the behaviors of sum. And it is not quite as clear in this instance.

Note: I do not advocate using this in production code. It is merely to show that it is possible.

Edward Minnix
  • 2,889
  • 1
  • 13
  • 26