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'
>>>
Related
I came across an example in a Python textbook that used word[1:2] to slice a string. It was doing it this way to demonstrate that only one letter of the string would be sliced.
It got me thinking - is there ever a use case where one would use word[1:2] instead of just word[1], which returns the same result?
The unwritten rule is that slicing will return a sub-sequence and subscription will return an element. It just happens that for length one strings, these notions are equal. But there is a subtle API difference: slicing strings can not throw an IndexError
>>> s = "x"
>>> s[1:2]
''
>>> s[1]
IndexError: string index out of range
In some rare occasions this can be convenient/useful when you want to make a check and avoid the possibility of unhanded exception.
Perhaps also worth mentioning here: there is a more significant difference with bytestrings, for which slicing again returns substrings but subscription returns ordinals.
>>> b'xyz'[1]
121
>>> b'xyz'[1:2]
b'y'
Assuming that you're working with valid indices, for string slicing there's no difference, because a single element of a string is still itself a string (i.e. there's no difference between a "character" and a string that's one character long).
>>> word = 'asdf'
>>> word[1:2]
's'
>>> word[1]
's'
For other slicable objects (e.g. a list) the two may not be equivalent:
>>> word = ['a', 's', 'd', 'f']
>>> word[1:2]
['s']
>>> word[1]
's'
word[1] is different from word[1:2]. word[1] is returning the value of list item with index 1. But also word[1:2] is a list slice which returns the list in the position of 1.
example:
word = ['a', 'b', 'c']
print(word[1])
#output: b
#but also
print(word[1:2])
#output: ['b']
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.
Is there a way to disable breaking string with list. For example:
>>> a = "foo"
>>> b = list()
>>> b.append(list(a))
>>> b
>>>[['f', 'o', 'o']]
Is there a way to have a list inside of a list with string that is not "broken", for example [["foo"],["bar"]]?
Very esay:
>>> a = "foo"
>>> b = list()
>>> b.append([a])
>>> b
[['foo']]
Do this:
>>> a = "foo"
>>> b = list()
>>> b.append([a])
>>> b
[["foo"]]
The reason this happens is that the list function works by taking each element of the sequence you pass it and putting them in a list. A string in Python is a sequence, the elements of the sequence are the individual characters.
Having this abstract concept of a "sequence" means that a lot of Python functions can work on multiple data types, as long as they accept a sequence. Once you get used to this idea, hopefully you'll start finding this concept more useful than surprising.
you sound like you want to break on word boundaries instead of on each letter.
Try something like
a = "foo bar"
b = list()
b.append(a.split(' ')) # [['foo', 'bar']]
Example with RegEx (to support multiple consecutive spaces) :
import re
a = "foo bar"
b.append(re.split(r'\s+', a)) # [['foo', 'bar']]
I have the list it contain int ,float and string:
lists = [10, "test", 10.5]
How Can i convert above list to string? I have tried:
val = ','.join(lists)
print val
I am getting error like this:
sequence item 0: expected string, int found
How can I solve this issue?
Firstly convert integers to string using strusing map function then use join function-
>>> ','.join(map(str,[10,"test",10.5]) )#since added comma inside the single quote output will be comma(,) separated
>>> '10,test,10.5'
Or if you want to convert each element of list into string then try-
>>> map(str,[10,"test",10.5])
>>> ['10', 'test', '10.5']
Or use itertools for memory efficiency(large data)
>>>from itertools import imap
>>>[i for i in imap(str,[10,"test",10.5])]
>>>['10', 'test', '10.5']
Or simply use list comprehension
>>>my_list=['10', 'test', 10.5]
>>>my_string_list=[str(i) for i in my_list]
>>>my_string_list
>>>['10', 'test', '10.5']
The easiest way is to send the whole thing to str() or repr():
>>> lists = [10, "test", 10.5]
>>> str(lists)
"[10, 'test', 10.5]"
repr() may produce a different result from str() depending on what's defined for each type of object in the list. The point of repr() is that you can send such strings back to eval() or ast.literal_eval() to get the original object back:
>>> import ast
>>> lists = [10, "test", 10.5]
>>> ast.literal_eval(repr(lists))
[10, 'test', 10.5]
a = ['b','c','d']
strng = ''
for i in a:
strng +=str(i)
print strng
The error you are getting because join wants elements to be string type, but in your list there is integer too, so 1st you have to convert them to type string.
you can use list comprehension and str and join to join them
>>> lists = [10,"test",10.5]
>>> ",".join(str(x) for x in lists)
You have to pass each item in your list as a string into the ','.join(sequence). Consider using:
val = ','.join([str(item) for item in lists])
print val
If you want to convert each element in the list to a string, you could do it simply using a for-loop.
for i in range(len(lists)):
lists[i] = str(lists[i])
Alternatively, if you want to make one string where all elements are joined together, you could edit the code above slightly.
string_of_lists = ""
for i in lists:
string_of_lists += str(i)
As you can tell, this is another way of doing it, apart from the other solutions using join.
I hope I helped!
This is also possible. Here x variable is list.
>>> '%s'*len(x) % tuple(x)
As mentioned here
list=['a/b/c', 'd/e/f']
file_list_string= ' '.join(list)
file_list_string= ' '.join(str(file) for file in list)
import functools
lists = [10,"test",10.5]
print(functools.reduce(lambda x,y:x+","+y,list(map(str,lists))))
You could always do it the dirty way:
list_name = ["a", "b", "c"];
string_name = "";
for c in list_name:
string_name += c
print(string_name)
OUTPUT:
"abc"
That should work with ints, floats, and strings, always converting them to string type.
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