Related
I'm wondering if it's possible to take a string e.g. str(input()) and split it into individual chars, then add them to a list. I'm trying to make a simple script (something similar to a hangman game) and at the beginning I wrote this:
x=input('Choose word: ').lower()
letters=[]
letters.append(list(x))
print(letters)
but this code appends the whole list to a list and not individual chars
Edit: this outputs [['o', 'u', 't', 'p', 'u', 't']] meaning that the whole list got appended as one item, but I want this to output ['o', 'u', 't', 'p', 'u', 't'], how do I make it append individual chars and not the whole list
You are simply wrapping the char list in another list.
Try this one-liner instead:
print(list(x))
If you want to remove a character:
letters = list(x)
letters.remove('o')
print(letters)
Use extend instead of append function.
#Extend
x=input('Choose word: ').lower()
letters=[]
letters.extend(list(x))
print(letters)
# ['p', 'y', 't', 'h', 'o', 'n']
And to remove a character from a list while retaining position as blank after removing, use replace while within a list:
y=input("Choose a letter to remove: ").lower()
removed=[s.replace(y,'') for s in letters]
print(removed)
#['p', '', 't', 'h', 'o', 'n']
I hope this help, unless its different from what you want. Then let me know. Otherwise, happy coding!
You don't need to create an empty list and then populate it with individual letters. Simply apply the list() function directly for the user input to create it:
letters = list(input('Choose word: ').lower())
print(letters)
For adding letters from the other user input, use the same approach with the .extend() method:
letters.extend(input('Choose word: ').lower()) # No need to use list() here
A simple one liner:
x = input().lower().split()
print(x)
here we are taking the input and then we are converting to lowercase and then using the split function which will split the string on white spaces you can split the string on whatever string you feel like just give the string you want to split on as the argument in the split function for example:
x = input().lower().split(',')
print(x)
this will split on the ',' so you can give the input in csv format
You may use the + operator (preferably in the form of an augmented assignment statement, i.e. +=, for extending the list to an iterable.
No need to use the list() function here, because the string is iterable:
letters = []
letters += input('Choose word: ').lower()
print(letters)
this outputs [['o', 'u', 't', 'p', 'u', 't']] meaning that the whole
list got appended as one item, but i want this to output ['o', 'u', 't', 'p', 'u', 't']
Based on you comment, you can use:
x = [*input('Choose word: ').lower()]
print(x)
# ['p', 'y', 't', 'h', 'o', 'n']
Demo
I have some input that looks like the following:
A,B,C,"D12121",E,F,G,H,"I9,I8",J,K
The comma-separated values can be in any order. I'd like to split the string on commas; however, in the case where something is inside double quotation marks, I need it to both ignore commas and strip out the quotation marks (if possible). So basically, the output would be this list of strings:
['A', 'B', 'C', 'D12121', 'E', 'F', 'G', 'H', 'I9,I8', 'J', 'K']
I've had a look at some other answers, and I'm thinking a regular expression would be best, but I'm terrible at coming up with them.
Lasse is right; it's a comma separated value file, so you should use the csv module. A brief example:
from csv import reader
# test
infile = ['A,B,C,"D12121",E,F,G,H,"I9,I8",J,K']
# real is probably like
# infile = open('filename', 'r')
# or use 'with open(...) as infile:' and indent the rest
for line in reader(infile):
print line
# for the test input, prints
# ['A', 'B', 'C', 'D12121', 'E', 'F', 'G', 'H', 'I9,I8', 'J', 'K']
I am doing a python project for my Intro to CSC class. We are given a .txt file that is basically 200,000 lines of single words. We have to read in the file line by line, and count how many times each letter in the alphabet appears as the first letter of a word. I have the count figured out and stored in a list. But now I need to print it in the format
"a:10,898 b:9,950 c:17,045 d:10,596 e:8,735
f:11,257 .... "
Another aspect is that it has to print 5 of the letter counts per line, as I did above.
This is what I am working with so far...
def main():
file_name = open('dictionary.txt', 'r').readlines()
counter = 0
totals = [0]*26
alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
for i in file_name:
for n in range(0,26):
if i.startswith(alphabet[n]):
totals[n] = totals[n]+1
print(totals)
main()
This code currently outputs
[10898, 9950, 17045, 10675, 7421, 7138, 5998, 6619, 6619, 7128, 1505, 1948, 5393, 10264, 4688, 6079, 15418, 890, 10790, 20542, 9463, 5615, 2924, 3911, 142, 658]
I would highly recommend using a dictionary to store the counts. It will greatly simplify your code, and make it much faster. I'll leave that as an exercise for you since this is clearly homework. (other hint: Counter is even better). In addition, right now your code is only correct for lowercase letters, not uppercase ones. You need to add additional logic to either treat uppercase letters as lowercase ones, or treat them independently. Right now you just ignore them.
Having said that, the following will get it done for your current format:
print(', '.join('{}:{}'.format(letter, count) for letter, count in zip(alphabet, total)))
zip takes n lists and generates a new list of tuples with n elements, with each element coming from one of the input lists. join concatenates a list of strings together using the supplied separator. And format does string interpolation to fill in values in a string with the provided ones using format specifiers.
python 3.4
the solution is to read the line of the file into words variable below in cycle and use Counter
from collections import Counter
import string
words = 'this is a test of functionality'
result = Counter(map(lambda x: x[0], words.split(' ')))
words = 'and this is also very cool'
result = result + Counter(map(lambda x: x[0], words.split(' ')))
counters = ['{letter}:{value}'.format(letter=x, value=result.get(x, 0)) for x in string.ascii_lowercase]
if you print counters:
['a:3', 'b:0', 'c:1', 'd:0', 'e:0', 'f:1', 'g:0', 'h:0', 'i:2', 'j:0', 'k:0', 'l:0', 'm:0', 'n:0', 'o:1', 'p:0', 'q:0', 'r:0', 's:0', 't:3', 'u:0', 'v:1', 'w:0', 'x:0', 'y:0', 'z:0']
Just for fun, I wrote this simple function to reverse a string in Python:
def reverseString(s):
ret = ""
for c in s:
ret = c + ret
return ret
Now, if I pass in the following two strings, I get interesting results.
print reverseString("Pla\net")
print reverseString("Plan\et")
The output of this is
te
alP
te\nalP
My question is: Why does the special character \n get translated into a new line when passed into the function, but not when the function parses it together by reversing n\? Also, how could I stop the function from parsing \n and instead return n\?
You should take a look at the individual character sequences to see what happens:
>>> list("Pla\net")
['P', 'l', 'a', '\n', 'e', 't']
>>> list("Plan\et")
['P', 'l', 'a', 'n', '\\', 'e', 't']
So as you can see, \n is a single character while \e are two characters as it is not a valid escape sequence.
To prevent this from happening, escape the backslash itself, or use raw strings:
>>> list("Pla\\net")
['P', 'l', 'a', '\\', 'n', 'e', 't']
>>> list(r"Pla\net")
['P', 'l', 'a', '\\', 'n', 'e', 't']
The reason is that '\n' is a single character in the string. I'm guessing \e isn't a valid escape, so it's treated as two characters.
look into raw strings for what you want, or just use '\\' wherever you actually want a literal '\'
The translation is a function of python's syntax, so it only occurs during python's parsing of input to python itself (i.e. when python parses code). It doesn't occur at other times.
In the case of your programme, you have a string which by the time it is constructed as an object, contains the single character denoted by '\n', and a string which when constructed contains the sub-string '\e'. After you reverse them, python doesn't reparse them.
im trying to make my program run as i want it to, but i have some trouble with that, hope someone can help with that.
I wrote a program that takes a list of chars and assembles them to create words. Word ends when there is a " " in list. So it looks like that:
inp = ['r','e', 'e', 'l', ' ', 'y', 'e', 'l', 'l', 'o', 'w', ' ', 'g', 'e', 'l',' ', 'p','e','e','k']
outp = ['reel', 'yellow', 'gel', 'peek']
The code looks like this:
def mer(inp, outp=[]):
tail = 0
for item in inp:
if item == (" "):
inp[:tail] = ["".join(inp[:tail])]
outp.append(inp.pop(0))
inp.remove(item)
if ((" ") in inp) == False:
inp[:] = ["".join(inp[:])]
outp.append(inp.pop(0))
tail +=1
And now to get the output (in the case with the input like on top) i need to call mer two times. Is there a way to make it run untill the input list is empty, or maybe use a recursion?
It's just a programming exercise, so it can be probably all done better, but for now thats all i need.
You can use join and split:
>>> ''.join(inp).split()
['reel', 'yellow', 'gel', 'peek']
# recursion
from itertools import takewhile
def fun(x):
if not x:
return
y = list(takewhile(lambda i:i!=' ', x))
yield ''.join(y)
for z in fun(x[len(y)+1:]):
yield z
list(fun(['r','e', 'e', 'l', ' ', 'y', 'e', 'l', 'l', 'o', 'w', ' ', 'g', 'e', 'l',' ', 'p','e','e','k']))
I know you asked for a method using recursion, but the most pythonic method in this case is to join the characters together, then split them.
outp = "".join(input).split(" ")
And now to get the output (in the case with the input like on top) i need to call mer two times.
The problem with your algorithm is that you are modifying the list while you iterate over it. This is a naughty and unsafe thing to be doing.
After "reel" is put into outp, inp is ['y', 'e', 'l', 'l', 'o', 'w', ' ', 'g', 'e', 'l',' ', 'p','e','e','k']. But the next character that will be examined by the loop is - at least in the CPython implementation - not the 'y' of 'yellow', but the 'w'. This is because the iteration internally stores an index (which happens to be in sync with the tail variable that you update manually) and uses that to grab elements. The listiterator created behind the scenes to implement the for-loop is utterly unaware of changes to the list that it's iterating over, and thus can't adjust to keep the "same position" (and who knows what you really mean by that, anyway?).
You can see this for yourself if you add a couple of "trace" print statements to the code to show the state of the variables at various points.
Anyway, since the iterator is at the 'w' at this point, it will find the space next and extract 'yellow' just fine; but next it will move to the 'k' of "peek", missing the space after 'gel', and it won't run any of the code in your second if-case, either, because the space between 'gel' and 'peek' is still in the buffer (you didn't really think clearly enough about the real end condition).
If you really, really want to do everything the hard way instead of just writing ''.join(inp).split(' '), you could fix the problem by tracking a beginning-of-word and end-of-word index, slicing out sublists, joining them and putting the resulting words into the output, and leaving the input alone. While we're at it:
functions should use the return value to return data; passing in an outp parameter is silly - let's just return a list of words.
We can use the built-in enumerate function to get indices that match up with the list elements as we iterate.
I have no idea what "mer" means.
You use way too many parentheses, and comparing to boolean literals (True and False) is poor style.
So, the corrected code using the original algorithm:
def words_from(chars):
begin = 0 # index of beginning of current word
result = [] # where we store the output
for i, char in enumerate(chars):
if char == ' ':
result.append(''.join(chars[begin:i]))
begin = i + 1
# At the end, make one more word from the chars after the last space.
result.append(''.join(chars[begin:]))
return result
You should definitely use join and split for this, but since the question specifically asks for a recursive solution, here is an answer that uses one.
This is meant as an exercise in recursion only, this code should not be used.
def join_split(inp, outp=None):
if not inp:
return outp
if inp[0] == ' ':
return join_split(inp[1:], (outp or ['']) + [''])
if outp is None:
return join_split(inp[1:], [inp[0]])
outp[-1] += inp[0]
return join_split(inp[1:], outp)
>>> join_split(['r','e', 'e', 'l', ' ', 'y', 'e', 'l', 'l', 'o', 'w', ' ', 'g', 'e', 'l',' ', 'p','e','e','k'])
['reel', 'yellow', 'gel', 'peek']