2

I have a list of words and their meanings:

wm = ['mendacious',
 'dishonest',
 'mendicant',
 'beggar',
 'meretricious',
 'gaudy; specious; falsely attractive',
 'mesmerize',
 'to hypnotize',
 'metamorphosis',
 'change; transformation']

Every word is followed by its meaning. So mendacious means dishonest, mendicant means beggar and so on. Words which have multiple meanings have their meanings separated by a ;. For example 'meretricious' has meanings gaudy; specious; falsely attractive.

What I want to do is to combine word-meaning pairs such that that my final list is this:

['mendacious : dishonest','mendicant : beggar','meretricious : gaudy; specious; falsely attractive','mesmerize : to hypnotize', 'metamorphosis : change; transformation']

How can I do this ?

damores
  • 2,251
  • 2
  • 18
  • 31
Vishesh Shrivastav
  • 2,079
  • 2
  • 16
  • 34

4 Answers4

2

You need to iterator over the list in pairs, and there's a simple idiom to do this by ziping up 2 of the same iter:

>>> i = iter(wm)
>>> [' : '.join(s) for s in zip(i, i)]
['mendacious : dishonest',
 'mendicant : beggar',
 'meretricious : gaudy; specious; falsely attractive',
 'mesmerize : to hypnotize',
 'metamorphosis : change; transformation']
AChampion
  • 29,683
  • 4
  • 59
  • 75
  • 1
    You don't need to explicitly declare another variable as an `iter` here - you can use `[' : '.join(s) for s in [iter(wm)] * 2]` instead – Jon Clements Nov 12 '16 at 16:58
  • @JonClements Yes, you can get away without defining `i` (yours is missing the `zip`) but I find it can be harder for new folks to follow as it uses a bit more magic `[' : '.join(s) for s in zip(*[iter(wm)]*2)]`. The principle is the same, using the same iterator twice to step through the list 2 at a time. – AChampion Nov 12 '16 at 17:19
  • Yeah - sorry missed the `*` :p – Jon Clements Nov 12 '16 at 17:24
  • @JonClements And `zip()` :p – AChampion Nov 12 '16 at 17:42
1

You can simply create a list of tuples using this code:

tl = zip(wm[0::2], wm[1::2])

This list will look like the following list:

[('mendacious', 'dishonest'), ('mendicant', 'beggar'), ('meretricious', 'gaudy; specious; falsely attractive'), ('mesmerize', 'to hypnotize'), ('metamorphosis', 'change; transformation')]

Then you can iterate through this list and concatenate each tuple.

#1

output = map(lambda t: t[0] + ':' + t[1], tl)

#2

output = [':'.join(t) for t in tl]
frogatto
  • 28,539
  • 11
  • 83
  • 129
1

A pythonic way of doing it:

res = ["%s : %s" % (wm[i], wm[i+1]) for i in range(0, len(wm), 2)]
print(res)

['mendacious : dishonest','mendicant : beggar','meretricious : gaudy; specious; falsely attractive','mesmerize : to hypnotize', 'metamorphosis : change; transformation']
maki
  • 431
  • 3
  • 8
1

My answer is very similar to AChampion's:

wm = [
    'mendacious',
    'dishonest',
    'mendicant',
    'beggar',
    'meretricious',
    'gaudy; specious; falsely attractive',
    'mesmerize',
    'to hypnotize',
    'metamorphosis',
    'change; transformation'
]

a = list(map(' : '.join, zip(*[iter(wm)] * 2)))
print(a)

This code may be a bit mysterious, so I'll try to explain what's going on.

iter(wm) creates an iterator object from wm. As the docs say, this is

an object representing a stream of data. Repeated calls to the iterator’s __next__() method (or passing it to the built-in function next()) return successive items in the stream.

We then duplicate the iterator and zip it. This lets us iterate over the items from the pair of iterators in parallel. But we don't actually have two separate iterators: we have two references to the one iterator object, so what we get is successive pairs of the items in wm. FWIW, this technique is discussed in How do you split a list into evenly sized chunks?.

We use map to call the ' : '.join method on each tuple of strings yielded by zip. Finally, we use list to convert the iterable returned by map into a list (in Python 2 this step isn't needed since the Python 2 map returns a list).


We can use this same technique to produce a dictionary instead of a list. A dictionary is a more useful structure for this data.

d = {k: v for k, v in zip(*[iter(wm)] * 2)}
print(d)

output

{'metamorphosis': 'change; transformation', 'mendicant': 'beggar', 'mendacious': 'dishonest', 'mesmerize': 'to hypnotize', 'meretricious': 'gaudy; specious; falsely attractive'}

And we can split the v strings into lists, which makes it easier to get at the individual words:

d = {k: v.split('; ') for k, v in zip(*[iter(wm)] * 2)}
print(d)

output

{'mendacious': ['dishonest'], 'mesmerize': ['to hypnotize'], 'meretricious': ['gaudy', 'specious', 'falsely attractive'], 'metamorphosis': ['change', 'transformation'], 'mendicant': ['beggar']}
Community
  • 1
  • 1
PM 2Ring
  • 54,345
  • 6
  • 82
  • 182