unirse con un separador agregado al final cuando no esté vacío

I need to append all elements in list_ a una string; at the end I need to add a suffix. A dot '.' has to separate all elements:

list_ = args[f(n) : f(n+1)]
if list_:
  string += '.' + '.'.join(list_) + '.' + suffix # works except when list_ is empty
  string += '.' + suffix
# list_ isn't used after this

Can I rewrite it in a simpler way in one line? If join added a separator after each element, it would just this:

string += '.' + '.'.join(args[f(n) : f(n+1)]) + '.' + suffix


I just learned that:

Slices are copies even if they are never assigned to: ¿Python hace cortes por referencia en cadenas?

But islice may be even worse since it iterates through the start of the list: itertools.islice en comparación con el segmento de la lista

Some alternatives are discussed here: Avoiding unnecessary slice copying in Python

preguntado el 01 de febrero de 12 a las 22:02

4 Respuestas

I would go with this (updated to reflect edits to the question):

'.'.join([''] + args[f(n):f(n+1)] + [suffix])

EDITAR: taking inspiration from sblom's and unutbu's answers, I might Realmente hacer esto:

from itertools import chain, islice
string = '.'.join(chain([string],  islice(args, f(n), f(n+1)), [suffix]))

if I were concerned about the memory cost of slicing args. You can use a tuple (string,) or a list [string] for the string and the suffix; given that they're one element each, there's no significant difference in memory usage or execution time, and since they're not being stored, you don't have to worry about mutability. I find the list syntax a little cleaner.

However: I'm not sure if Python actually creates a new list object for a slice that is only going to be used, not assigned to. If it doesn't, then given that args is a proper list, using islice encima [f(n):f(n+1)]doesn't save you much of anything, and in that case I'd just go with the simple approach (up top). If args were a generator or other lazily evaluated iterable with a very large number of elements, luego islice might be worth it.

Respondido 02 Feb 12, 02:02

This seems perfect in my specific situation. - max

If list_ is a generator (or can be trivially changed to be one), you can get away without materializing any lists at all using chain() desde itertools.

from itertools import chain

(This takes inspiration from David Zaslavsky's answer.)

Respondido 02 Feb 12, 02:02

I like this approach - but I'm not sure if it's easy to create a generator that returns a slice of an existing list? - max

Claro, puedes usar itertools.islice(list_, f(n), f(n+1)). - David Z

@DavidZaslavsky: I guess in light of what I've learned (see the update to the question), the islice has terrible performance on a list... I would use this approach if I had a true generator. - max

Also riffing on David Zaslavsky answer:

string = '.'.join([string] + list_ + [suffix])

The advantage of doing it this way is that there is no addition of strings.

contestado el 23 de mayo de 17 a las 15:05

string += ('.' + '.'.join(list_) if list_ else '') + '.' + suffix 

Respondido 02 Feb 12, 02:02

Sorry, forgot to mention that list_ is actually an expression; I was hoping to avoid creating an extra variable for it (see update to my question).. - max

Well, you already do that on your code... Then go with David's code if you don't matter creating 2 extra lists. - JBernardo

Yes, in my case, it's not a performance issue, just making the code look simple. - max

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.