-1

I have a list of strings. I need to add a string to all of them, and then a second string to only two of them. I am trying the following:

[s + ' help ' for s in [ ['me '].extend(['with ' + t for t in ['things', 'please']]) ] ]

What I would expect is the following:

['me help ', 'with things help ', 'with please help ']

Nothing happens when I try to run this in iPython. It seems to have a problem with using the extend method on a 'newly created' list. I am unsure, and relatively new to python.

EDIT:

To be more explicit, in the above example, the original list would be:

['me', 'things', 'please']

I need to add 'help ' to all of them, and 'with ' to only the latter two.

And I get an error when running the above line of code:

TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'

Second Edit:

I am more focused on the location of the elements. I want a string added to every element of the list, excluding the first, and then a second string added to the entire new list. My above approach was a first stab at what it should be (in the most 'pythonic' way), but it does not work. I understand why it does not work, but I am unsure how to rewrite the above line into something that will work.

lukehawk
  • 1,423
  • 3
  • 22
  • 48
  • Is the list static length, and what is the list? Which two do you need to add the second string too? Also what is the output you are getting? – Jacobr365 Mar 15 '17 at 14:33
  • I do not know what you mean by 'static' The original list is dynamic, which needs static things added to it. I can handle that, though. I just need to know how to do this portion. – lukehawk Mar 15 '17 at 14:43
  • I mean static as is, is the list always the same size. I guess I mean, are you always adding the second string to the last two in the list, or always the second and third element? – Jacobr365 Mar 15 '17 at 14:46
  • You need to come up with some generic rules (especially for this optional addition). Under what criteria optional scripts should be included? Position in list? Original value in list? Something else? – Łukasz Rogalski Mar 15 '17 at 14:46
  • i am adding the string to everything in the list but the first element. The size (for now) is static, but I could foresee it being dynamic. So, I would like to keep it dynamic with respects to the size of the original list. – lukehawk Mar 15 '17 at 14:47
  • I think you all are focusing on the wrong thing. I just want to know how to add a couple strings to various portions of the list. TO be more specific, add a string to everything but the first, then add a second string to everything. I know my example is simplistic. I did that to provide an easily reproducible example for you to work with. – lukehawk Mar 15 '17 at 14:49
  • The `TypeError` results from trying to concatenate `s == None` and 'help'. The result of `['me'].extend(...)` is `None`. Not the extended list as you assume. – wolfmanx Mar 15 '17 at 14:49
  • @wolfmanx - Yes. Exactly. I am aware of why the error happened, but am unaware of how to get the extended list I want at that point.Is there a way? – lukehawk Mar 15 '17 at 14:53
  • @lukehawk Sure, see [answer below](http://stackoverflow.com/a/42813325/2127439) – wolfmanx Mar 15 '17 at 15:12

5 Answers5

2

In case you want to index the elements in the list you can use this:

 s=['me', 'things', 'please']
   ['with ' + x + ' help' if x!=s[0] else x+' help' for x in s]
Donald Duck
  • 8,409
  • 22
  • 75
  • 99
1

Unless you define a function, which extends a list and returns the result:

def lext(l, lx):
    l.extend(lx)
    return l

(which python already does):

import itertools
lext = itertools.chain

and employ it this way:

[s + ' help ' for s in lext(['me '], ['with ' + t for t in ['things', 'please']])]

you have to do it step by step:

inp = ['me', 'things', 'please']
out1 = [ s + ' help' for s in inp]
out2 = [ out1[0] ]
out2.extend(('with ' + s for s in out1[1:]))

Welcome to the wonderful world of procedures and functions, aka. commands and expressions :)

wolfmanx
  • 481
  • 5
  • 12
0

If it's string match based:

['with ' + t + ' help' if t != 'me' else t + ' help' for t in ['me', 'things', 'please']]

This will create a list of strings based if an item is me or not.

Produces:

['me help', 'with things help', 'with please help']

If it's positional:

If you always know the position, this might help:

x = ['me', 'things', 'please']
word_pos = 1
['{} help'.format(i) for i in x[:word_pos]] + ['with {} help'.format(i) for i in x[word_pos:]]

Which produces:

['me help', 'with things help', 'with please help']

Either one can be a one-liner, but I'd strongly suggest expanding these as they quickly get fudgy to work with.

Torxed
  • 22,866
  • 14
  • 82
  • 131
  • I like your thinking, and yes it would work. But I am more focused on the location of the element in the list. Good thinking. Thanks. – lukehawk Mar 15 '17 at 14:50
  • @lukehawk I'm not sure it's possible to get indexing into this one-liner in a efficient manner. I just assumed you needed this because of linguistic reasons (where certain phrases would sound bad otherwise). If no one else can come up with a better option I'll see if I can't work more magic. – Torxed Mar 15 '17 at 14:54
  • Thank you for your attempts, and yes that is the crux of what I am asking. Its one of those problems that seems relatively straightforward, and something some wizard like yourself should have an elegant answer for, but I am pretty inexperienced in the 'pythonic' ways, and at a loss. – lukehawk Mar 15 '17 at 14:58
  • @lukehawk Not entirely sure if this is pythonic or not.. I'd consider expanding into a 'for` loop in this case. But I updated my answer with a solution that is both positional and can handle if cases. That is the use of joining two lists and use the iterator operator to format each "half". `['{} help'.format(i) for i in x[:1]] + ['with {} help'.format(i) for i in x[1:]]` where `x` is the list of strings that you gave in your first edit. – Torxed Mar 15 '17 at 15:15
0

This is a possible solution to achieve exactly what you wrote you expect:

items = ['me', 'things', 'please']
new_items = []

for index, value in enumerate(items):
    # Prepend to every item but the first
    if i > 0:
        v = "with %s" % v

    # Append to every item
    v = "%s help " % v

    new_items.append(v)

print(new_items)  # outputs: ['me help ', 'with things help ', 'with please help ']

This appends help to every item, and prepends with to every but the first item.

Pit
  • 3,606
  • 1
  • 25
  • 34
0

I think I figured this out. Thanks all for your help, but this is (most simply) what I was trying to get at:

[s + ' help ' for s in  ['me '] + ['with ' + t for t in ['things', 'please']]   ]

which produces

['me  help ', 'with things help ', 'with please help ']

It was just the extend method that I needed to replace with + to concatenate the list.

lukehawk
  • 1,423
  • 3
  • 22
  • 48
  • So, accept this answer. If you ever need to worry about space, look into `itertools.chain(listone, listtwo)` (e.g. http://stackoverflow.com/a/1724975/2127439) and generators in general: `(s + ' help ' for s in itertools.chain(('me',), ('with ' + t for t in ('things', 'please'))))`. That would be the *pythonic* way to do it efficiently :) – wolfmanx Mar 15 '17 at 15:54
  • Thanks! I appreciate you helping me drive even closer to that goal. – lukehawk Mar 16 '17 at 16:26