String building using join

Discussion in 'Python' started by gervaz, Dec 31, 2010.

  1. gervaz

    gervaz Guest

    Hi all, I would like to ask you how I can use the more efficient join
    operation in a code like this:

    >>> class Test:

    .... def __init__(self, v1, v2):
    .... self.v1 = v1
    .... self.v2 = v2
    ....
    >>> def prg(l):

    .... txt = ""
    .... for x in l:
    .... if x.v1 is not None:
    .... txt += x.v1 + "\n"
    .... if x.v2 is not None:
    .... txt += x.v2 + "\n"
    .... return txt
    ....
    >>> t1 = Test("hello", None)
    >>> t2 = Test(None, "ciao")
    >>> t3 = Test("salut", "hallo")
    >>> t = [t1, t2, t3]
    >>>
    >>> prg(t)

    'hello\nciao\nsalut\nhallo\n'

    The idea would be create a new list with the values not None and then
    use the join function... but I don't know if it is really worth it.
    Any hint?

    >>> def prg2(l):

    .... e = []
    .... for x in l:
    .... if x.v1 is not None:
    .... e.append(x.v1)
    .... if x.v2 is not None:
    .... e.append(x.v2)
    .... return "\n".join(e)
    ....
    >>> prg2(t)

    'hello\nciao\nsalut\nhallo'

    Thanks, Mattia
    gervaz, Dec 31, 2010
    #1
    1. Advertising

  2. On 12/31/2010 7:22 AM gervaz said...
    > Hi all, I would like to ask you how I can use the more efficient join
    > operation in a code like this:
    >
    >>>> class Test:

    > ... def __init__(self, v1, v2):
    > ... self.v1 = v1
    > ... self.v2 = v2
    > ...
    >>>> def prg(l):

    > ... txt = ""
    > ... for x in l:
    > ... if x.v1 is not None:
    > ... txt += x.v1 + "\n"
    > ... if x.v2 is not None:
    > ... txt += x.v2 + "\n"
    > ... return txt
    > ...
    >>>> t1 = Test("hello", None)
    >>>> t2 = Test(None, "ciao")
    >>>> t3 = Test("salut", "hallo")
    >>>> t = [t1, t2, t3]
    >>>>
    >>>> prg(t)

    > 'hello\nciao\nsalut\nhallo\n'
    >
    > The idea would be create a new list with the values not None and then
    > use the join function... but I don't know if it is really worth it.
    > Any hint?
    >
    >>>> def prg2(l):


    return "\n".join([x for x in l if x])

    Emile



    > ... e = []
    > ... for x in l:
    > ... if x.v1 is not None:
    > ... e.append(x.v1)
    > ... if x.v2 is not None:
    > ... e.append(x.v2)
    > ... return "\n".join(e)
    > ...
    >>>> prg2(t)

    > 'hello\nciao\nsalut\nhallo'
    >
    > Thanks, Mattia
    Emile van Sebille, Dec 31, 2010
    #2
    1. Advertising

  3. gervaz

    gervaz Guest

    On 31 Dic 2010, 16:43, Emile van Sebille <> wrote:
    > On 12/31/2010 7:22 AM gervaz said...
    >
    >
    >
    >
    >
    > > Hi all, I would like to ask you how I can use the more efficient join
    > > operation in a code like this:

    >
    > >>>> class Test:

    > > ...     def __init__(self, v1, v2):
    > > ...         self.v1 = v1
    > > ...         self.v2 = v2
    > > ...
    > >>>> def prg(l):

    > > ...     txt = ""
    > > ...     for x in l:
    > > ...         if x.v1 is not None:
    > > ...             txt += x.v1 + "\n"
    > > ...         if x.v2 is not None:
    > > ...             txt += x.v2 + "\n"
    > > ...     return txt
    > > ...
    > >>>> t1 = Test("hello", None)
    > >>>> t2 = Test(None, "ciao")
    > >>>> t3 = Test("salut", "hallo")
    > >>>> t = [t1, t2, t3]

    >
    > >>>> prg(t)

    > > 'hello\nciao\nsalut\nhallo\n'

    >
    > > The idea would be create a new list with the values not None and then
    > > use the join function... but I don't know if it is really worth it.
    > > Any hint?

    >
    > >>>> def prg2(l):

    >
    >              return "\n".join([x for x in l if x])
    >
    > Emile
    >
    >
    >
    > > ...     e = []
    > > ...     for x in l:
    > > ...         if x.v1 is not None:
    > > ...             e.append(x.v1)
    > > ...         if x.v2 is not None:
    > > ...             e.append(x.v2)
    > > ...     return "\n".join(e)
    > > ...
    > >>>> prg2(t)

    > > 'hello\nciao\nsalut\nhallo'

    >
    > > Thanks, Mattia- Nascondi testo citato

    >
    > - Mostra testo citato -- Nascondi testo citato
    >
    > - Mostra testo citato -


    Sorry, but it does not work

    >>> def prg3(l):

    .... return "\n".join([x for x in l if x])
    ....
    >>> prg3(t)

    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 2, in prg3
    TypeError: sequence item 0: expected str instance, Test found
    gervaz, Jan 2, 2011
    #3
  4. On 1/2/2011 9:43 AM gervaz said...
    > On 31 Dic 2010, 16:43, Emile van Sebille<> wrote:
    >> On 12/31/2010 7:22 AM gervaz said...
    >>
    >>
    >>
    >>
    >>
    >>> Hi all, I would like to ask you how I can use the more efficient join
    >>> operation in a code like this:

    >>
    >>>>>> class Test:
    >>> ... def __init__(self, v1, v2):
    >>> ... self.v1 = v1
    >>> ... self.v2 = v2
    >>> ...
    >>>>>> def prg(l):
    >>> ... txt = ""
    >>> ... for x in l:
    >>> ... if x.v1 is not None:
    >>> ... txt += x.v1 + "\n"
    >>> ... if x.v2 is not None:
    >>> ... txt += x.v2 + "\n"
    >>> ... return txt
    >>> ...
    >>>>>> t1 = Test("hello", None)
    >>>>>> t2 = Test(None, "ciao")
    >>>>>> t3 = Test("salut", "hallo")
    >>>>>> t = [t1, t2, t3]

    >>
    >>>>>> prg(t)
    >>> 'hello\nciao\nsalut\nhallo\n'

    >>
    >>> The idea would be create a new list with the values not None and then
    >>> use the join function... but I don't know if it is really worth it.
    >>> Any hint?

    >>
    >>>>>> def prg2(l):

    >>
    >> return "\n".join([x for x in l if x])
    >>
    >> Emile
    >>
    >>
    >>
    >>> ... e = []
    >>> ... for x in l:
    >>> ... if x.v1 is not None:
    >>> ... e.append(x.v1)
    >>> ... if x.v2 is not None:
    >>> ... e.append(x.v2)
    >>> ... return "\n".join(e)
    >>> ...
    >>>>>> prg2(t)
    >>> 'hello\nciao\nsalut\nhallo'

    >>
    >>> Thanks, Mattia- Nascondi testo citato

    >>
    >> - Mostra testo citato -- Nascondi testo citato
    >>
    >> - Mostra testo citato -

    >
    > Sorry, but it does not work


    Oh -- you want a working solution, not a hint? OK.

    class Test:
    def __init__(self, v1, v2):
    self.v1 = v1
    self.v2 = v2


    t1 = Test("hello", None)
    t2 = Test(None, "ciao")
    t3 = Test("salut", "hallo")
    t = [t1, t2, t3]


    "\n".join([y for x in t for y in [x.v1,x.v2] if y])

    Emile

    >
    >>>> def prg3(l):

    > ... return "\n".join([x for x in l if x])
    > ...
    >>>> prg3(t)

    > Traceback (most recent call last):
    > File "<stdin>", line 1, in<module>
    > File "<stdin>", line 2, in prg3
    > TypeError: sequence item 0: expected str instance, Test found
    Emile van Sebille, Jan 2, 2011
    #4
  5. gervaz

    gervaz Guest

    On 2 Gen, 19:14, Emile van Sebille <> wrote:
    > On 1/2/2011 9:43 AM gervaz said...
    >
    >
    >
    >
    >
    > > On 31 Dic 2010, 16:43, Emile van Sebille<>  wrote:
    > >> On 12/31/2010 7:22 AM gervaz said...

    >
    > >>> Hi all, I would like to ask you how I can use the more efficient join
    > >>> operation in a code like this:

    >
    > >>>>>> class Test:
    > >>> ...     def __init__(self, v1, v2):
    > >>> ...         self.v1 = v1
    > >>> ...         self.v2 = v2
    > >>> ...
    > >>>>>> def prg(l):
    > >>> ...     txt = ""
    > >>> ...     for x in l:
    > >>> ...         if x.v1 is not None:
    > >>> ...             txt += x.v1 + "\n"
    > >>> ...         if x.v2 is not None:
    > >>> ...             txt += x.v2 + "\n"
    > >>> ...     return txt
    > >>> ...
    > >>>>>> t1 = Test("hello", None)
    > >>>>>> t2 = Test(None, "ciao")
    > >>>>>> t3 = Test("salut", "hallo")
    > >>>>>> t = [t1, t2, t3]

    >
    > >>>>>> prg(t)
    > >>> 'hello\nciao\nsalut\nhallo\n'

    >
    > >>> The idea would be create a new list with the values not None and then
    > >>> use the join function... but I don't know if it is really worth it.
    > >>> Any hint?

    >
    > >>>>>> def prg2(l):

    >
    > >>               return "\n".join([x for x in l if x])

    >
    > >> Emile

    >
    > >>> ...     e = []
    > >>> ...     for x in l:
    > >>> ...         if x.v1 is not None:
    > >>> ...             e.append(x.v1)
    > >>> ...         if x.v2 is not None:
    > >>> ...             e.append(x.v2)
    > >>> ...     return "\n".join(e)
    > >>> ...
    > >>>>>> prg2(t)
    > >>> 'hello\nciao\nsalut\nhallo'

    >
    > >>> Thanks, Mattia- Nascondi testo citato

    >
    > >> - Mostra testo citato -- Nascondi testo citato

    >
    > >> - Mostra testo citato -

    >
    > > Sorry, but it does not work

    >
    > Oh -- you want a working solution, not a hint?  OK.
    >
    > class Test:
    >       def __init__(self, v1, v2):
    >           self.v1 = v1
    >           self.v2 = v2
    >
    > t1 = Test("hello", None)
    > t2 = Test(None, "ciao")
    > t3 = Test("salut", "hallo")
    > t = [t1, t2, t3]
    >
    > "\n".join([y for x in t for y in [x.v1,x.v2] if y])
    >
    > Emile
    >
    >
    >
    >
    >
    > >>>> def prg3(l):

    > > ...     return "\n".join([x for x in l if x])
    > > ...
    > >>>> prg3(t)

    > > Traceback (most recent call last):
    > >    File "<stdin>", line 1, in<module>
    > >    File "<stdin>", line 2, in prg3
    > > TypeError: sequence item 0: expected str instance, Test found- Nascondi testo citato

    >
    > - Mostra testo citato -- Nascondi testo citato
    >
    > - Mostra testo citato -


    Thanks Emile, despite that now the solution runs in quadratic time I
    guess. I could also provide a __str__(self) representation, but in my
    real code I don't have access to the class. Also using str() on an
    empty object (i.e. None), the representation is 'None'.

    Ciao,

    Mattia
    gervaz, Jan 2, 2011
    #5
  6. gervaz

    gervaz Guest

    On 2 Gen, 22:37, gervaz <> wrote:
    > On 2 Gen, 19:14, Emile van Sebille <> wrote:
    >
    >
    >
    >
    >
    > > On 1/2/2011 9:43 AM gervaz said...

    >
    > > > On 31 Dic 2010, 16:43, Emile van Sebille<>  wrote:
    > > >> On 12/31/2010 7:22 AM gervaz said...

    >
    > > >>> Hi all, I would like to ask you how I can use the more efficient join
    > > >>> operation in a code like this:

    >
    > > >>>>>> class Test:
    > > >>> ...     def __init__(self, v1, v2):
    > > >>> ...         self.v1 = v1
    > > >>> ...         self.v2 = v2
    > > >>> ...
    > > >>>>>> def prg(l):
    > > >>> ...     txt = ""
    > > >>> ...     for x in l:
    > > >>> ...         if x.v1 is not None:
    > > >>> ...             txt += x.v1 + "\n"
    > > >>> ...         if x.v2 is not None:
    > > >>> ...             txt += x.v2 + "\n"
    > > >>> ...     return txt
    > > >>> ...
    > > >>>>>> t1 = Test("hello", None)
    > > >>>>>> t2 = Test(None, "ciao")
    > > >>>>>> t3 = Test("salut", "hallo")
    > > >>>>>> t = [t1, t2, t3]

    >
    > > >>>>>> prg(t)
    > > >>> 'hello\nciao\nsalut\nhallo\n'

    >
    > > >>> The idea would be create a new list with the values not None and then
    > > >>> use the join function... but I don't know if it is really worth it.
    > > >>> Any hint?

    >
    > > >>>>>> def prg2(l):

    >
    > > >>               return "\n".join([x for x in l if x])

    >
    > > >> Emile

    >
    > > >>> ...     e = []
    > > >>> ...     for x in l:
    > > >>> ...         if x.v1 is not None:
    > > >>> ...             e.append(x.v1)
    > > >>> ...         if x.v2 is not None:
    > > >>> ...             e.append(x.v2)
    > > >>> ...     return "\n".join(e)
    > > >>> ...
    > > >>>>>> prg2(t)
    > > >>> 'hello\nciao\nsalut\nhallo'

    >
    > > >>> Thanks, Mattia- Nascondi testo citato

    >
    > > >> - Mostra testo citato -- Nascondi testo citato

    >
    > > >> - Mostra testo citato -

    >
    > > > Sorry, but it does not work

    >
    > > Oh -- you want a working solution, not a hint?  OK.

    >
    > > class Test:
    > >       def __init__(self, v1, v2):
    > >           self.v1 = v1
    > >           self.v2 = v2

    >
    > > t1 = Test("hello", None)
    > > t2 = Test(None, "ciao")
    > > t3 = Test("salut", "hallo")
    > > t = [t1, t2, t3]

    >
    > > "\n".join([y for x in t for y in [x.v1,x.v2] if y])

    >
    > > Emile

    >
    > > >>>> def prg3(l):
    > > > ...     return "\n".join([x for x in l if x])
    > > > ...
    > > >>>> prg3(t)
    > > > Traceback (most recent call last):
    > > >    File "<stdin>", line 1, in<module>
    > > >    File "<stdin>", line 2, in prg3
    > > > TypeError: sequence item 0: expected str instance, Test found- Nascondi testo citato

    >
    > > - Mostra testo citato -- Nascondi testo citato

    >
    > > - Mostra testo citato -

    >
    > Thanks Emile, despite that now the solution runs in quadratic time I
    > guess. I could also provide a __str__(self) representation, but in my
    > real code I don't have access to the class. Also using str() on an
    > empty object (i.e. None), the representation is 'None'.
    >
    > Ciao,
    >
    > Mattia- Nascondi testo citato
    >
    > - Mostra testo citato -


    And this one is another working solution...

    >>> def prg4(l):

    .... s = []
    .... for x in l:
    .... s.extend(set([x.v1, x.v2]) - set([None]))
    .... return "\n".join(s)
    ....
    >>> prg4(t)

    'hello\nciao\nhallo\nsalut'

    My original question was just related to the fact that I read that the
    string concatenation in expensive and it sould be used the join()
    function but now probably it is better to stick with the first
    implementation, the simplest one.

    Ciao,

    Mattia
    gervaz, Jan 2, 2011
    #6
  7. Hello,

    On Sun, Jan 02, 2011 at 10:11:50AM -0800, Alex
    Willmer wrote:
    > def prg3(l):
    > return '\n'.join([str(x) for x in l if x])


    just one fix (one fix one fix one fix):
    return '\n'.join([str(x) for x in l if x is not None])

    --
    With best regards,
    xrgtn
    Alexander Gattin, Jan 3, 2011
    #7
  8. On Mon, Jan 3, 2011 at 3:07 AM, gervaz <> wrote:
    > On 2 Gen, 19:14, Emile van Sebille <> wrote:
    >> <snip>
    >>
    >> class Test:
    >>       def __init__(self, v1, v2):
    >>           self.v1 = v1
    >>           self.v2 = v2
    >>
    >> t1 = Test("hello", None)
    >> t2 = Test(None, "ciao")
    >> t3 = Test("salut", "hallo")
    >> t = [t1, t2, t3]
    >>
    >> "\n".join([y for x in t for y in [x.v1,x.v2] if y])
    >>
    >>
    >>

    > <snip>
    >
    > Thanks Emile, despite that now the solution runs in quadratic time I
    > guess. I could also provide a __str__(self) representation, but in my
    > real code I don't have access to the class. Also using str() on an
    > empty object (i.e. None), the representation is 'None'.
    >


    Since no one else has mentioned it, I'll just point out that Emile's
    solution does not run in quadratic time. It has the same number of
    operations as the originally posted code.

    That str(None) results in "None" is not a problem because of the "if
    y" test in the list comprehension.

    --
    regards,
    kushal
    Kushal Kumaran, Jan 4, 2011
    #8
  9. gervaz <> writes:

    > Hi all, I would like to ask you how I can use the more efficient join
    > operation in a code like this:
    >
    >>>> class Test:

    > ... def __init__(self, v1, v2):
    > ... self.v1 = v1
    > ... self.v2 = v2
    > ...


    >>>> def prg(l):

    > ... txt = ""
    > ... for x in l:
    > ... if x.v1 is not None:
    > ... txt += x.v1 + "\n"
    > ... if x.v2 is not None:
    > ... txt += x.v2 + "\n"
    > ... return txt
    > ...


    You can change the prg() function above slightly to make it a generator
    function:

    def genprg(l):
    for x in l:
    if x.v1 is not None:
    yield x.v1
    if x.v2 is not None:
    yield x.v2

    Then you can rewrite prg using join:

    def prg(l):
    return '\n'.join(genprg(l))

    This way you save yourself from creating a list. I know this is not the
    one liner that others have suggested but it shows a general way of
    transforming a piece of code in order to make use of generator functions.

    --
    Arnaud
    Arnaud Delobelle, Jan 4, 2011
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. laurent
    Replies:
    7
    Views:
    1,918
    Joe Smith
    May 27, 2004
  2. Alan Silver
    Replies:
    0
    Views:
    870
    Alan Silver
    Jun 5, 2006
  3. googleboy
    Replies:
    1
    Views:
    906
    Benji York
    Oct 1, 2005
  4. Midex
    Replies:
    24
    Views:
    882
  5. Gunter Hansen
    Replies:
    5
    Views:
    917
    Roedy Green
    Sep 1, 2011
Loading...

Share This Page