I have a line of code which is:
D = {'h' : 'hh' , 'e' : 'ee'}
str = 'hello'
data = ''.join(map(lambda x:D.get(x,x),str))
print data
this gives an output -> hheello
I am trying to understand how does map function work here. Does map take each character of
the string and compare it with dictionary key, and give back the corresponding key value?
How does it do for each character here? There is no iteration. Is there any good example to understand this better?
There is no loop because map requires an "iterable" (i.e. an object on which you can do an iteration) and does the loop itself.
map, if not present natively, could be implemented as:
def map(f, it):
return [f(x) for x in it]
or, even more explicitly, as:
def map(f, it):
result = []
for x in it:
result.append(f(x))
return result
In Python a string is an iterable, and on iteration loops over the characters in the string. For example
map(ord, "hello")
returns
[104, 101, 108, 108, 111]
because those are the character codes for the chars in the string.
Map just applies the function to each item of a list. E.g.,
map(lambda x: 10*x, [1,2,3,4])
gives
[10, 20, 30, 40]
It takes individual elements of str. Following is the readable code for the same implementation:
D = { 'h' : 'hh' , 'e' : 'ee'}
str = 'hello'
returns = [] # create list for storing return value from function
def myLambda(x): # function does lambda
return D.get(x,x)
for x in str: #map==> pass iterable
returns.append(myLambda(x)) #for each element get equivalent string from dictionary and append to list
print ''.join(returns) #join for showing result
Generally speaking, a map operation works like this:
MAP (f,L) returns L'
Input:
L is a list of n elements [ e1 , e2 , ... , en ]
f is a function
Output
L' is the list L after the application of f to each element individually: [ f(e1) , f(e2) , ... , f(en) ]
So, in your case, the join operation, which operates on lists, starts with the empty string and repeatedly concatenates each element e obtained in the following way:
Take a character x from str; return D.get(x,x)
Note that the above (which is the explaining of the map operation) will give you 'hh' and 'ee' with input 'h' and input 'e' respectively, while it will leave the other characters as they are.
Since str is a string, map() will apply the function (lambda in this case) to every item of the string. [map()][2] works on iterables and sequences, so it can work in a string because a string is a sequence.
Try this so you get the idea:
str2 = "123"
print map(int, str2)
>>> [1, 2, 3]
In this case you are casting each letter in str2 to int:
int("1") -> 1
int("2") -> 2
int("3") -> 3
and return them in a list:
[1, 2, 3]
Note: Don't use Python built-in names as names of variables. Don't use str as the name of a variable because you are hiding its built-in implementation. Use str1, my_str o, s ... instead.
Related
I wanna use lists;
by that I mean a = b in a list
let = {
"a", "b" (meaning a is b)
}
then how can I use this list to replace all characters in a input string
string = "stringa"
characters = [
"a", "b",
]
dic = {}
for l1 in zip(characters):
dic[l1]
result = ""
for letter in string:
result = result + dic[letter]
print(result)
input('Press Any Key To Exit')
I tried this but it didnt work any help is appeciarated
I think your problem is in the zip(characters) line.
you need more than one list inorder to zip.
When you do zip to just one list, the output is as seen here:
c = ['a','b']
for i in zip(c):
print(i)
# ('a',)
# ('b',)
and this also is what your error shows you KeyError: ('a',)
EDIT:
if you want to have "stringa" converted to "stringb" you have another issue.
What you need to do is:
string = "stringa"
dic = {'a':'b', 'b':'a'}
result = ""
for letter in string:
if letter in dic.keys():
letter = dic[letter]
result+=letter
print(result)
# stringb
When converting a list into a dictionary, you use slices to turn the list into two, for zipping together. zip returns a tuple iterator, so you need two for loop variables:
for l1, l2 in zip(characters[::2], characters[1::2]):
dic[l1] = l2
dic[l2] = l1
The [::2] gets every other character starting with the first one. The [1::2] gets every other character starting with the second one.
If you want to avoid a dictionary, and do a two-way replacement, then one way to do it is to do the replacements in the zip loop:
result = string
for l1, l2 in zip(characters[::2], characters[1::2]):
result = result.replace(l1, '#')
result = result.replace(l2, l1)
result = result.replace('#', l2)
The # is a temporary placeholder to avoid undoing the replacement we just did. You can set that to be any character that won't show up in the strings.
If I want to disassemble a string into a list, do some manipulation with the original decimal values, and then assemble the string from the list, what is the best way?
str = 'abc'
lst = list(str.encode('utf-8'))
for i in lst:
print (i, chr(int(i+2)))
gives me a table.
But I would like to create instead a presentation like 'abc', 'cde', etc.
Hope this helps
str_ini = 'abc'
lst = list(str_ini.encode('utf-8'))
str_fin = [chr(v+2) for v in lst]
print(''.join(str_fin))
To convert a string into a list of character values (numbers), you can use:
s = 'abc'
vals = [ord(c) for c in s]
This results in vals being the list [97, 98, 99].
To convert it back into a string, you can do:
s2 = ''.join(chr(val) for val in vals)
This will give s2 the value 'abc'.
If you prefer to use map rather than comprehensions, you can equivalently do:
vals = list(map(ord, s))
and:
s2 = ''.join(map(chr, vals))
Also, avoid using the name str for a variable, since it will mask the builtin definition of str.
Use ord on the letters to retrieve their decimal ASCII representation, and then chr to convert them back to characters after manipulating the decimal value. Finally use the str.join method with an empty string to piece the list back together into a str:
s = 'abc'
s_list = [ord(let) for let in s]
s_list = [chr(dec + 2) for dec in s_list]
new_s = ''.join(s_list)
print(new_s) # every character is shifted by 2
Calling .encode on the string converts to a bytes string instead, which is likely not what you want. Additionally, you don't want to be using built-ins as the names for variables, because then you will no longer be able to use the built-in keyword in the same scope.
From this answer I learned how can I count occurrences of any character in a string using a map,
Count Vowels in String Python
Here is my code which counts occurance of any vowels in a string,
name = "maverick dean"
vowels = 'aeiou'
x = list(map(name.lower().count, 'aeiou'))
As you can see I used list to put each value of a map in a list.
Which gives this output,
[2, 2, 1, 0, 0]
My desire output is
[ "a:2", "e:2", "i:1", "o:0", "u:0" ]
Now I understand I can use for loop to do it, but is there any other way to map output of x directly so that it shows alongside the actual vowel?
You can use lambda function for this:
x = list(map(lambda v: "{}:{}".format(v, name.lower().count(v)), vowels))
print(x)
# ['a:2', 'e:2', 'i:1', 'o:0', 'u:0']
You can use a list comprehension
x = ["%s:%d" % (letter, name.lower().count(letter)) for letter in vowels]
or you could even use a zip onto the original list i.e.
x = ["%s:%d" % (l,c) for l, c in zip(vowels, map(name.lower().count, vowels))]
Currently I have a long list that has elements like this:
['01/01/2013 06:31, long string of characters,Unknown'].
How would I split each element into:
['01/01/2013 06:31], [long string of characters],[Unknown]? Can I even do that?
I tried variable.split(","), but I get "AttributeError: 'list' object has no attribute 'split'".
Here's my code:
def sentiment_analysis():
f = open('C:\path', 'r')
write_to_list = f.readlines()
write_to_list = map(lambda write_to_list: write_to_list.strip(), write_to_list)
[e.split(',') for e in write_to_list]
print write_to_list[0:2]
f.close()
return
I'm still not getting it, I'd appreciate any help!
Solution
You are given this:
['01/01/2013 06:31, long string of characters,Unknown']
Alright. If you know that there is only this one long string in this list, just extract the only element:
>>> x = ['01/01/2013 06:31, long string of characters,Unknown']
>>>
>>> y = x[0].split(",") # extract only element and split by comma
>>> print(y) # list of strings, with one depth
['01/01/2013 06:31', ' long string of characters', 'Unknown']
Now for whatever reasons, you actually want each eletent of the outer list to be a list with one string in it. That is easy enough to do - simply use map and anonymous functions:
... # continuation from snippet above
...
>>> z = map(lambda s: [s], y) # encapsulates each elem of y in a list
>>> print(z)
[['01/01/2013 06:31'], [' long string of characters'], ['Unknown']]
There you have it.
One-Liner Conclusion
No list comprehensions, no for loops, no generators. Just really simple functional programming and anonymous functions.
Given original list l,
res = map(lambda s: [s],
l[0].split(","))
List comprehension!
>>> variable = ['01/01/2013 06:31, long string of characters,Unknown']
>>> [x.split(',') for x in variable]
[['01/01/2013 06:31', ' long string of characters', 'Unknown']]
But wait, that's nested more than you wanted...
>>> itertools.chain.from_iterable(x.split(',') for x in variable)
<itertools.chain object at 0x109180fd0>
>>> list(itertools.chain.from_iterable(x.split(',') for x in variable))
['01/01/2013 06:31', ' long string of characters', 'Unknown']
Hear me out, I do not simply want someone to solve this problem for me. I know it is not 100% complete yet, but currently when I run the program I get an error about "Can't convert 'list' object to str implicitly" I'm looking for help on how to fix this and why it is does this.
Here is the problem
Write code to print out each thing in the list of lists, L, with a '*' after it like
1*2*3*4*...8*a*b*c*d*
This requires knowing the print statement and using the end or sep argument option
Here is my list, sorry for not putting it in earlier
L = [[1,2,3,4],[5,6,7,8],['a','b','c','d']]
Here is my code at the moment
def ball(x): #random function name with one parameter
q = '' #
i = 0
if type(x) != list: #verifies input is a list
return"Error"
for i in x: #Looks at each variable in list
for j in i: #Goes into second layer of lists
q = q + j + '*'
print(q)
The reason for your error
"Can't convert 'list' object to str implicitly"
is that you're using the wrong variable in your nested for loops. Where you're concatenating values to your q variable, you mistakenly put q = q + i when you wanted q = q + j. You also will want to cast the value of j as a string so it can be concatenated with q. In order to get your desired output, you can simply add an asterisk into that statement - something like the following: q = q + str(j) + '*'. On a completely unrelated note, your else statement that just has "Mistake" in it should be removed completely - it doesn't follow an if and it doesn't actually return or assign to a variable.
Note that this is not the most elegant way to go about solving this problem. I agree with ilent2 that you should take a look at both list comprehension and the str.join() method.
If you have a list of strings,
myList = ['a', '123', 'another', 'and another']
You can join them using the str.join function:
Help on method_descriptor:
join(...)
S.join(iterable) -> string
Return a string which is the concatenation of the strings in the
iterable. The separator between elements is S.
myString = '#'.join(myList)
If your list contains mixed types or non-strings you need to convert each item to a string first:
anotherList = [1, 2, 'asdf', 'bwsg']
anotherString = '*'.join([str(s) for s in anotherList])
You might want to read about list comprehension or more about the join function. Note, the above doesn't print the output (unless you are using the interactive console), if you want the output to be printed you will need call print too
print myString
print anotherString
And, if you are working with lists-of-lists you may need to change how you convert each sub-list into a string (depending on your desired output):
myListList = [[1, 2, 3, 4], [2, 3, 6, 5], [6, 4, 3, 1]]
myOtherString = '#'.join(['*'.join([str(s) for s in a]) for a in myListList])
The last line is a little complicated to read, you might want to rewrite it as a nested for loop instead.