Select non empty elements of list in Python [duplicate] - python

This question already has answers here:
Joining multiple strings if they are not empty in Python
(3 answers)
Closed 5 years ago.
Given:
a = 'aaa'
b = ''
c = 'ccc'
d = ''
e = 'eee'
list = (a, b, c, d, e)
How can I get a string using all the non empty elements of the list ?
Desired output:
'aaa,ccc,eee'

Using a generator expression:
",".join(string for string in lst if len(string) > 0)
The ",".join() part is using the join() method of strings, which takes an iterable argument and outputs a new string that concatenates the items using "," as delimiter.
The generator expression between parenthesis is being used to filter empty strings out of the list.
The original list doesn't change.

The shortest thing you can do is
','.join(filter(None, mytuple))
(I renamed list to mytuple in oder to not shadow the builtin list.)

You can use a generator-expression:
','.join(s for s in list if s)
which outputs:
'aaa,ccc,eee'
Why?
This takes advantage of the fact that an empty string evaluates to False.
This can be seen clearer through some examples:
>>> if "a":
... print("yes")
...
yes
>>> if " ":
... print("yes")
...
yes
>>> if "":
... print("yes")
...
>>>
So the generator says: for each string in list, keep 'if string' - i.e. if the string is not empty.
We then finally use the str.join method that will take each string in the iterator that is passed into it (here a generator) and concatenate them together with whatever the str is. So here we use a ',' as the string to get the desired result.
A little example of this:
>>> ','.join(['abc', 'def', 'ghi'])
'abc,def,ghi'
**As a side note, you shouldn't name your variable list as it overrides the built-in list() function:
>>> list((1, 2, 3))
[1, 2, 3]
>>> list = 1
>>> list((1, 2, 3))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable

You can try this one too:
a = 'aaa'
b = ''
c = 'ccc'
d = ''
e = 'eee'
tup = (a, b, c, d, e)
res = ",".join(filter(lambda i: not i=='', tup))
print(res)
The output will be:
aaa,ccc,eee
It is also a good practice not to use list as a variable name, as it is a reserved keyword from Python.

Related

Why does augmented assignment behave differently when adding a string to a list [duplicate]

This question already has answers here:
Adding a string to a list using augmented assignment
(7 answers)
Different behaviour for list.__iadd__ and list.__add__
(3 answers)
Why does += behave unexpectedly on lists?
(9 answers)
Closed 4 years ago.
I am in a very interesting situation and I am so surprised.
actually I thought both i += 1 and i = i + 1 are same. but it'is not same in here;
a = [1,2]
a += "ali"
and output is [1,2,"a","l","i"]
but if I write like that;
a = [1,2]
a = a + "ali"
it doesn't work.
I am really confused about this.
are they different?
Short answer
The + operator concatenates lists while the += operator extends a list with an iterable.
Long answer
The + operator concatenate lists to return a new list...
l1 = l2 = []
l1 = l1 + [1]
l1 # [1]
l2 # []
... while the += operator extends a list, by mutating it.
l1 = l2 = []
l1 += [1]
l1 # [1]
l2 # [1]
What allows different behaviours is that + calls the __add__ method while += calls the __iadd__ method.
In your example, you provided a string to the __iadd__ method, which is equivalent to doing l.extend('ali'). In particular, you can extend a list with any iterable, but concatenation arguments must both be lists.
Although, there is a slight difference between list.__iadd__ and list.extend. The former returns the mutated list, while the later does not.
In python, since you can't declare static types, this behavior doesn't show up, but if you look at C++, if you declare int a = 4 as an integer and then do a += 5.4, a will become 9, whereas a = a + 5.4 will break.
The reason for this is that a += b and a = a + b aren't the same. In python terms, a += b is just a.__iadd__(b) and a = a + b is a = a.__add__(b), or if that doesn't exist, a = b.__radd__(a). You can't add lists and strings together using + so the second code doesn't work, but += works because it automatically casts certain types to each other, namely converting iterables to each other. You cannot do a = []; a += "" but you can do it vice-versa because you can convert the string to a list unambiguously using list("...").
>>> a = [1,2]
>>> a = a + "ali"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "str") to list
For list data type use the .append method:
>>> a = [1,2]
>>> a.append("ali")
>>> a
[1, 2, 'ali']
The String in Python is defined as a series of characters in a row. So, these "characters" are added to the "list" type as the characters, not as "String". When you want use the += adding operator for the list type, you must specify the type of the added variable or value using square brackets:
>>> a = [1,2]
>>> a += ["ali"]
>>> a
[1, 2, 'ali']
>>> a += ["foo",3,"bar"]
>>> a
[1, 2, 'ali', 'foo', 3, 'bar']

Python function to modify string

I was asked once to create a function that given a string, remove a few characters from the string.
Is it possible to do this in Python?
This can be done for lists, for example:
def poplist(l):
l.pop()
l1 = ['a', 'b', 'c', 'd']
poplist(l1)
print l1
>>> ['a', 'b', 'c']
What I want is to do this function for strings.
The only way I can think of doing this is to convert the string to a list, remove the characters and then join it back to a string. But then I would have to return the result.
For example:
def popstring(s):
copys = list(s)
copys.pop()
s = ''.join(copys)
s1 = 'abcd'
popstring(s1)
print s1
>>> 'abcd'
I understand why this function doesn't work. The question is more if it is possible to do this in Python or not? If it is, can I do it without copying the string?
Strings are immutable, that means you can not alter the str object. You can of course construct a new string that is some modification of the old string. But you can thus not alter the s object in your code.
A workaround could be to use a container:
class Container:
def __init__(self,data):
self.data = data
And then the popstring thus is given a contain, it inspect the container, and puts something else into it:
def popstring(container):
container.data = container.data[:-1]
s1 = Container('abcd')
popstring(s1)
But again: you did not change the string object itself, you only have put a new string into the container.
You can not perform call by reference in Python, so you can not call a function:
foo(x)
and then alter the variable x: the reference of x is copied, so you can not alter the variable x itself.
Strings are immutable, so your only main option is to create a new string by slicing and assign it back.
#removing the last char
>>> s = 'abcd'
>>> s = s[:-1]
=> 'abc'
Another easy to go method maybe to use list and then join the elements in it to create your string. Ofcourse, it all depends on your preference.
>>> l = ['a', 'b', 'c', 'd']
>>> ''.join(l)
=> 'abcd'
>>> l.pop()
=> 'd'
>>> ''.join(l)
=> 'abc'
Incase you are looking to remove char at a certain index given by pos (index 0 here), you can slice the string as :
>>> s='abcd'
>>> s = s[:pos] + s[pos+1:]
=> 'abd'
You could use bytearray instead:
s1 = bytearray(b'abcd') # NB: must specify encoding if coming from plain string
s1.pop() # now, s1 == bytearray(b'abc')
s1.decode() # returns 'abc'
Caveats:
if you plan to filter arbitrary text (i.e. non pure ASCII), this is a very bad idea to use bytearray
in this age of concurrency and parallelism, it might be a bad idea to use mutation
By the way, perhaps it is an instance of the XY problem. Do you really need to mute strings in the first place?
You can remove parts of a strings and assign it to another string:
s = 'abc'
s2 = s[1:]
print(s2)
You wont do that.. you can still concatenate but you wont pop until its converted into a list..
>>> s = 'hello'
>>> s+='world'
>>> s
'helloworld'
>>> s.pop()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'pop'
>>> list(s).pop()
'd'
>>>
But still You can play with Slicing
>>> s[:-1]
'helloworl'
>>> s[1:]
'elloworld'
>>>

Writing a nested loop in python [duplicate]

This question already has answers here:
how to change [1,2,3,4] to '1234' using python
(2 answers)
Closed 7 years ago.
I'm a Python beginner struggling to write code that uses the list myList = [['A','B','C'],[4,5,​6],[7,8,9]] and generates the output below:
Input:
myList = [['A','B','C'],[4,5,​6],[7,8,9]]
Expected output: (by line)
-A-B-C-
-4-5-6-
-7-8-9-
I've tried a few different things but am not sure how to approach the confluence of strings and integers in the same list.
I can get:
>>> for i in range (0,myList_len):
... print ("-".join(myList[i]))
...
A-B-C
But I can't get this to work for the numbers. Any help would be much appreciated!
You could use map to convert from int to str
for l1 in myList:
print '-' + '-'.join(map(str, l1)) + '-'
When you try to join numbers, you get the following error:
TypeError: sequence item 0: expected str instance, int found
This is because str.join() only works with str items in the iterable, but you pass it int objects instead.
So in order to properly join them, you need to convert them to strings first. You can either do that by calling str on every item using map, or by using a list comprehension:
>>> lst = [4, 5, 6]
>>> '-'.join(map(str, lst))
'4-5-6'
>>> '-'.join([str(x) for x in lst])
'4-5-6'
The "join" operator expects a list of strings, so you have to turn your numbers to strings first, using the "str" operator that turns anything into a string.
for l in myList:
print '-' + '-'.join([str(x) for x in l]) + '-'
join works on strings, not numbers. You need to convert:
print ("-".join(str(num) for num in myList[i]))
Now, just add the hyphens at start and finish, and you're done.
Try the following:
for sublist in myList:
print("-".join(map(str, sublist)))
The output is:
A-B-C
4-5-6
7-8-9
If you want leading and trailing hyphens as well, use:
for sublist in myList:
print("-" + "-".join(map(str, sublist)) + "-")
The output is:
-A-B-C-
-4-5-6-
-7-8-9-
The for loop iterates over the sublists. The map(str, sublist) call applies str to each element of the sublist, converting it to a string. Without this, your non-string entries (i.e., numbers) were causing errors when passed to join.

Converting a set to a string

So I'm supposed to create a function that takes any sort of iterable input and converts it into a string of that input separated by spaces. For example, if you were to call iteration_to_string("abcd") it would return "a b c d " (the space at the end is allowed). or if [1, 2, 3, 4] is the input, it should return "1 2 3 4 ". All I have so far is how to turn the input into a set and Im confused where to go to turn it into a string. I assume it would be adding something into the for loop that would somehow concatenate the inputs together with a space but Im not sure how to do that. Any help is appreciated!
def iteration_to_string (data):
new = set()
for i in range (len(data)):
new.add(data[i])
return " ".join(new)
your code might not work for list containing element int like [1,2,3,4] because join takes string
so you can convert them to int before join like this:
>>> def my_join(x):
... return " ".join(map(str, x))
...
>>> my_join([1, 2, 3, 4])
'1 2 3 4'
you can use list comprehension, if you dont want to use map
>>> def my_join(x):
... return " ".join(str(element) for element in x))
>>> my_join(['a', 'b' ,'c', 'd'])
'a b c d'
for any iterable
' '.join(iterable)
will return a string with all the elements in iterable separated by a space. refer to str.join(iterable).
if the elements in iterable are not strings you need to
' '.join(str(item) for item in iterable)
(you can do this with any other string as well; ''.join(iterable) if you do not want any spaces in between).

Get the first character of the first string in a list?

How would I get the first character from the first string in a list in Python?
It seems that I could use mylist[0][1:] but that does not give me the first character.
>>> mylist = []
>>> mylist.append("asdf")
>>> mylist.append("jkl;")
>>> mylist[0][1:]
'sdf'
You almost had it right. The simplest way is
mylist[0][0] # get the first character from the first item in the list
but
mylist[0][:1] # get up to the first character in the first item in the list
would also work.
You want to end after the first character (character zero), not start after the first character (character zero), which is what the code in your question means.
Get the first character of a bare python string:
>>> mystring = "hello"
>>> print(mystring[0])
h
>>> print(mystring[:1])
h
>>> print(mystring[3])
l
>>> print(mystring[-1])
o
>>> print(mystring[2:3])
l
>>> print(mystring[2:4])
ll
Get the first character from a string in the first position of a python list:
>>> myarray = []
>>> myarray.append("blah")
>>> myarray[0][:1]
'b'
>>> myarray[0][-1]
'h'
>>> myarray[0][1:3]
'la'
Numpy operations are very different than python list operations.
Python has list slicing, indexing and subsetting. Numpy has masking, slicing, subsetting, indexing.
These two videos cleared things up for me.
"Losing your Loops, Fast Numerical Computing with NumPy" by PyCon 2015:
https://youtu.be/EEUXKG97YRw?t=22m22s
"NumPy Beginner | SciPy 2016 Tutorial" by Alexandre Chabot LeClerc:
https://youtu.be/gtejJ3RCddE?t=1h24m54s
Indexing in python starting from 0. You wrote [1:] this would not return you a first char in any case - this will return you a rest(except first char) of string.
If you have the following structure:
mylist = ['base', 'sample', 'test']
And want to get fist char for the first one string(item):
myList[0][0]
>>> b
If all first chars:
[x[0] for x in myList]
>>> ['b', 's', 't']
If you have a text:
text = 'base sample test'
text.split()[0][0]
>>> b
Try mylist[0][0]. This should return the first character.
If your list includes non-strings, e.g. mylist = [0, [1, 's'], 'string'], then the answers on here would not necessarily work. In that case, using next() to find the first string by checking for them via isinstance() would do the trick.
next(e for e in mylist if isinstance(e, str))[:1]
Note that ''[:1] returns '' while ''[0] spits IndexError, so depending on the use case, either could be useful.
The above results in StopIteration if there are no strings in mylist. In that case, one possible implementation is to set the default value to None and take the first character only if a string was found.
first = next((e for e in mylist if isinstance(e, str)), None)
first_char = first[0] if first else None

Categories

Resources