Conversion of Strings to list - python

Can someone please help me with a simple code that returns a list as an output to list converted to string? The list is NOT like this:
a = u"['a','b','c']"
but the variable is like this:
a = '[a,b,c]'
So,
list(a)
would yield the following output
['[', 'a', ',', 'b', ',', 'c', ']']
instead I want the input to be like this:
['a', 'b', 'c']
I have even tried using the ast.literal_eval() function - on using which I got a ValueError exception stating the argument is a malformed string.

There is no standard library that'll load such a list. But you can trivially do this with string processing:
a.strip('[]').split(',')
would give you your list.
str.strip() will remove any of the given characters from the start and end; so it'll remove any and all [ and ] characters from the start until no such characters are found anymore, then remove the same characters from the end. That suffices nicely for your input sample.
str.split() then splits the remainder (minus the [ and ] characters at either end) into separate strings at any point there is a comma:
>>> a = '[a,b,c]'
>>> a.strip('[]')
'a,b,c'
>>> a.strip('[]').split(',')
['a', 'b', 'c']

Let us use hack.
import string
x = "[a,b,c]"
for char in x:
if char in string.ascii_lowercase:
x = x.replace(char, "'%s'" % char)
# Now x is "['a', 'b', 'c']"
lst = eval(x)
This checks if a character is in the alphabet(lowercase) if it is, it replaces it with a character with single quotes around it.
Why not use this solution ?:
Fails for duplicate elements
Fails for elements with more than single characters.
You need to be careful about confusing single quote and double quotes
Why use this solution ?:
There are no reasons to use this solution rather than Martijn's. But it was fun coding it anyway.
I wish you luck in your problem.

Related

Union Operators to Dict

How can I convert
x = 'a=b&c=d'
to
{'a':'b', 'c':'d'}
without explicitly looking and replacing & and = to , and : respectively?
You have a DSL (domain specific language) for defining a dict. You have to parse the string, then evaluate the result. Luckily, that's as simple as
d = dict(kv.split("=", 1) for kv in x.split("&"))
I might be misinterpreting the meaning of "explicitly looking and replacing". I would argue you can't do it without doing so.
But I also see no reason to avoid that.
x = 'a=b&c=d'
mydict = dict(map(lambda y: y.split('='), x.split('&')))
What this does is best understood reading from the inside out.
It takes the string 'a=b&c=d' and turns it into a list of substrings that used to have an ampersand in between them.
It takes one such 'a=b' string and splits again, this time on the equal sign.
This operation is performed on the whole list, so we end up with a list of lists.
[['a', 'b'], ['c', 'd']]
dict() turns that into a dictionary
>>> x
'a=b&c=d'
>>> mydict[x[0]]=x[2]
>>> mydict[x[4]]=x[6]
>>> mydict
{'a': 'b', 'c': 'd'}
>>> #note that '&' and '=' are not "looked for" nor replaced

Using word[1:2] instead of just word[1]?

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']

How to solve this task with lists?

Making a list from mainlist and from subslists
As chepner said, try write your own code without list comprehension and then modify your own code.
def pyramid(base, char):
return [ ['']*num_empty + [char]*num_char + ['']*num_empty for num_empty, num_char in enumerate(list(range(base, 0, -2)))][::-1]
I'd recommend breaking up the problems into two steps:
Generate the list of pyramid bricks (without the empty spaces)
Add in the empty spaces (as needed) to each element of that list
As for Step 1, you can easily accomplish it with this function:
def pyramid(base, char):
result = [[char] * i for i in range(1, base+1, 2)]
return result
Do you see what it's doing? It's looping through a range of odd numbers, and for each number, it is constructing a list of chars. Each constructed list will be an element of the returned result list.
So if you call pyramid(5, 'A'), you'll get:
[['A'], ['A', 'A', 'A'], ['A', 'A', 'A', 'A', 'A']]
This solution does not account for the empty spaces, however. To handle those empty spaces, you could either:
Run the result through a second list comprehension, or:
Edit the first (and only) list comprehension to include the proper number of spaces at the beginning and end of each sub-list.
I'll let you decide how to implement this for yourself. I hope this helps!

replacing the integers in a string with x's without error handling

I have been trying to figure out a simple way to replace the integers within a string with x's in python. I was able to get something ok by doing the following:
In [73]: string = "martian2015"
In [74]: string = list(string)
In [75]: for n, i in enumerate(string):
....: try:
....: if isinstance(int(i), int):
....: string[n]='x'
....: except ValueError:
....: continue
This actually yields something like the following:
In [81]: string
Out[81]: ['m', 'a', 'r', 't', 'i', 'a', 'n', 'x', 'x', 'x', 'x']
In [86]: joiner = ""
In [87]: string = joiner.join(string)
In [88]: string
Out[88]: 'martianxxxx'
My question is: is there any way of getting the result in a simpler manner without relying on error/exception handling?
Yes, using regex and the re module:
import re
new_string = re.sub("\d", "x", "martin2015")
The string "\d" tells Python to search for all digits in the string. The second argument is what you want to replace all matches with, and the third argument is your input. (re.sub stands for "substitute")
You can use the str.isdigit function and list comprehension, like this
>>> data = "martian2015"
>>> "".join(["x" if char.isdigit() else char for char in data])
'martianxxxx'
The isdigit function will return True if all the characters in it are numeric digits. So, if it is a digit, then we use "x" otherwise we use the actual character itself.
You can actually use generator expression instead of list comprehension to do the same, like this
>>> "".join("x" if char.isdigit() else char for char in data)
'martianxxxx'
The only difference is generators are lazy evaluated, unlike the list comprehension which builds the entire list. The generator will give values only on demand. Read more about them here.
But in this particular case, with str.join, the list is built anyway.
If you are going to do this kind of replacement often, then you might want to know about str.translate and str.maketrans.
>>> mapping = str.maketrans("0123456789", "x" * 10)
>>> "martin2015".translate(mapping)
'martinxxxx'
>>> "10-03-2015".translate(mapping)
'xx-xx-xxxx'
>>>
The maketrans builds a dictionary with the character codes of values in the first string and the corresponding character in the second string. So, when we use the mapping with the translate, whenever it finds a character in the mapping, it will simply replace it with the corresponding value.
change isinstance to .isdigit
string = "martian2015"
for i in string:
if i.isdigit():
string.replace(i, "x")
(or regular expressions, regex / re )
In [102]: import string
In [103]: mystring
Out[103]: 'martian2015'
In [104]: a='x'*10
In [105]: leet=maketrans('0123456789',a)
In [106]: mystring.translate(leet)
Out[106]: 'martianxxxx'
If you don't know advance data process method, you can invoke string module to filter num string.
import string
old_string = "martin2015"
new_string = "".join([s if s not in string.digits else "x" for s in old_string ])
print new_string
# martinxxxx
Although I know my anwser is not the best solution, I want to offer different methods help people solve problems.

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