-1

I want to concatenate the two string elements in a list of tuples

I have this:

mylist = [('a', 'b'), ('c', 'd'), ('e', 'f'), ('g', 'h')]
myanswer = []

for tup1 in mylist:
   myanswer.append(tup1[0] + tup[1])

It's working but is there any easy way to do this? My real list has around 1000 items and I don't think a for loop is the most efficient way.

Expected output:

myanswer = ["ab", "cd", "ef", "gh"]
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 1
    Well, your question was confusing. You claimed it wasn't working, then correct it to working code and are asking for a more efficient way to do this. You do want to make sure you are asking the question correctly and clearly, with an example that is actually valid Python code – Martijn Pieters Mar 01 '19 at 11:31

1 Answers1

1

Use a list comprehension, and for just two elements, I'd use tuple unpacking and concatenation:

myanswer = [s1 + s2 for s1, s2 in mylist]

Another option is to use a formatted string literal:

myanswer = [f"{s1}{s2}" for s1, s2 in mylist]

Both are reasonably fast:

>>> from random import choice
>>> from string import ascii_letters
>>> from timeit import Timer
>>> testdata = [(choice(ascii_letters), choice(ascii_letters)) for _ in range(10000)]
>>> count, total = Timer('[f"{s1}{s2}" for s1, s2 in mylist]', 'from __main__ import testdata as mylist').autorange()
>>> print(f"List comp with f-string, 10k elements: {total / count * 1000000:7.2f} microseconds")
List comp with f-string, 10k elements: 1249.37 microseconds
>>> count, total = Timer('[s1 + s2 for s1, s2 in mylist]', 'from __main__ import testdata as mylist').autorange()
>>> print(f"List comp with concatenation, 10k elements: {total / count * 1000000:6.2f} microseconds")
List comp with concatenation, 10k elements: 1061.89 microseconds

Concatenation wins out here.

A list comprehension removes the need to look up the list object and its .append() method each time in a loop, see What is the advantage of a list comprehension over a for loop?

Formatted string literals where introduced in Python 3.6, and are easily the fastest way of composing strings with interpolated elements (even though they didn't start out that way).

I also tried out [itertools.starmap()] with [operator.add()] and [str.join()], but this doesn't appear to be competitive:

>>> count, total = Timer('list(starmap(add, mylist))', 'from __main__ import testdata as mylist; from itertools import starmap; from operator import add').autorange()
>>> print(f"itertools.starmap and operator.add, 10k elements: {total / count * 1000000:6.2f} microseconds")
itertools.starmap and operator.add, 10k elements: 1275.02 microseconds
>>> count, total = Timer('list(starmap(str.join, mylist))', 'from __main__ import testdata as mylist; from itertools import starmap').autorange()
>>> print(f"itertools.starmap and str.join, 10k elements: {total / count * 1000000:6.2f} microseconds")
itertools.starmap and str.join, 10k elements: 1564.79 microseconds

It does improve with more elements; by 1 million elements, map(starmap(add, largelist)) is winning by a small margin (133ms vs 140ms for a list comprehension with concatenation).

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343