user14864717
user14864717

Reputation: 35

Is there a more pythonic way to use multiple list comprehension?

There is snippet of code with list comprehensions of similar type/task. Each of iterable in comprehension formula is of numpy.array [(), (), ()] shape. Is there more 'pythonic', not so repetitive way to write this?

conv_zcr = [bytes(x) for x in zcr]
conv_stft = [bytes(x) for x in stft]
conv_spectral_centroid = [bytes(x) for x in spectral_centroid]

Upvotes: 0

Views: 96

Answers (4)

Bobby Ocean
Bobby Ocean

Reputation: 3294

It is not clear which orientation you want from the three lists. However, in general, if you want a collection of objects to undergo the same set of steps, then normally the easiest way to work with that data is to place that data in a list. For example,

lists = [zcr, stft, spectral_centroid] 

then if we want to apply bytes() to each entry in each list we can do so in several ways:

conv_lists = [[bytes(i) for i in l] for l in lists]
conv_lists = [list(map(bytes,l)) for l in lists]

if you want the elements oriented the other way, then you might want the zip() function:

conv_lists = [list(map(bytes,l)) for l in zip(*lists)] 

if you want to place that result in a np.array(), then wrap that in np.array():

import numpy as np
conv_lists = np.array([list(map(bytes,l)) for l in zip(*lists)])

Upvotes: 0

Verthais
Verthais

Reputation: 437

Well you can try ziping it together if they have same len i guess:

conv_zcr, conv_stft, conv_spectral_centroid = [
    (bytes(x), bytes(y), bytes(z))
    for x, y, z in zip(zcr, stft, spectral_centroid)
]

you probably can chain em if mixing outputs is not an issue:

out = [bytes(x) for x in itertools.chain(zcr, stft, spectral_centroid)]

you can probably map them to something of your liking:

out = [map(bytes, ar) for ar in [zcr, stft, spectral_centroid]]

Upvotes: 2

Blake Smith
Blake Smith

Reputation: 26

You could do


def byteify_lists(*lists):
    return [[bytest(x) for x in lst] for lst in lists]

conv_zcr, conv_stft, conv_spectral_centroid = byteifly_lists(zcr, stft, spectral_centroid)

Or in a single list comprehension


conv_zcr, conv_stft, conv_spectral_centroid = [[bytes(x) for x in lst] 
                                                for lst in 
                                                [zcr, stft, spetral_centroid]]

But honestly, the way you have it is fine.

Upvotes: 0

André C. Andersen
André C. Andersen

Reputation: 9375

You could use map(...) i suppose. But I don't think it is especially more pythonic.

conv_zcr = map(bytes, zcr)
conv_stft = map(bytes, stft)
conv_spectral_centroid = map(bytes, spectral_centroid)

Cast to list() like this list(map(bytes, zcr)) if you don't want a lazy loading map object.

Upvotes: 1

Related Questions