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
else:
  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

Editar

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
'.'.join(chain(('',),list_,(suffix,)))

(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.