Control Structure in Python - python

I am wondering why this piece of code:
wordlist = ['cat','dog','rabbit']
letterlist=[]
for aword in wordlist:
for aletter in aword:
if aletter not in letterlist:
letterlist.append(aletter)
print(letterlist)
prints ['c', 'a', 't', 'd', 'o', 'g', 'r', 'b', 'i']
while this code:
wordlist = ['cat','dog','rabbit']
letterlist=[]
for aword in wordlist:
for aletter in aword:
letterlist.append(aletter)
print(letterlist)
prints ['c', 'a', 't', 'd', 'o', 'g', 'r', 'a', 'b', 'b', 'i', 't']
I don't understand how the code is being computed and doesn't spell out all of 'rabbit' and/or why it spells out 'r', 'b', 'i'? Anyone know what's going on?

You are adding each unique letter to letterlist with this if block:
if aletter not in letterlist:
letterlist.append(aletter)
If the letter has already been seen, it does not get appended again. That means the second time you see a (in 'rabbit'), the second b (in 'rabbit') and the second and third time you see t, they aren't added to the list.

This part of the code if aletter not in letterlist: checks if the letter has already been added to the list. If it does, you wont add it again.
So basically you wont add any repeated characters. That's why the output is ['c', 'a', 't', 'd', 'o', 'g', 'r', 'b', 'i'] . No repeated letters there.
The second piece of code just iterates the whole list and appends to letterlist no matter what. That's why all letters are added, and you get ['c', 'a', 't', 'd', 'o', 'g', 'r', 'a', 'b', 'b', 'i', 't'] as result.

Related

Conditional statement to pull out last names from a list

I have a list of full names (titled "FullNames") and I am trying to pull out the last names. The problem is that some of the full names include middle names (e.g., some of the items in the list are "Craig Nelson" while others are "Craig T. Nelson") which stops me from using a simple list comprehension statement such as:
LastNames = ([x.split()[1] for x in FullNames])
Instead, I am trying to loop through the list with this code:
LastNames = []
for item in FullNames:
if '.' in FullNames:
LastNames.appened(item[2])
else:
LastNames.append(item[1])
print(LastNames)
However, I am just getting a bunch of letters back:
['u', 'a', 'e', 'i', 'o', 'a', 't', 'h', 'r', 'e', 'e', 'r', 'e', 'h', 'a', 'i', 't', 'a', 'r', 'a', 'i', 'e', 'o', 'e', 'e', 'a', 'r', 'o', 'a', 'y', 'i', 'e', 'e', 'o', 'o', 'e', 'e', 'a', 'i', 'i', 'e', 'm', 'a', 'a', 'a', 'n', 'e', 'a', 'r']
Is there a simple way around this?
def get_last(name):
return name.split(' ')[-1].split('.')[-1]
full_names = ["Craig T. Nelson", "Craig Nelson"]
output = list(map(get_last, full_names))
print(output)
#['Nelson', 'Nelson']

Python script to generate a word with specific structure and letter combinations

I want to write a really short script that will help me generate a random/nonsense word with the following qualities:
-Has 8 letters
-First letter is "A"
-Second and Fourth letters are random letters
-Fifth letter is a vowel
-Sixth and Seventh letters are random letters and are the same
-Eighth letter is a vowel that's not "a"
This is what I have tried so far (using all the info I could find and understand online)
firsts = 'A'
seconds = ['a','b','c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
thirds = ['a', 'e', 'i', 'o', 'u', 'y']
fourths = ['a','b','c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
fifths = ['a', 'e', 'i', 'o', 'u', 'y']
sixths = sevenths = ['a','b','c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
eighths = ['e', 'i', 'o', 'u', 'y']
print [''.join(first, second, third, fourth, fifth)
for first in firsts
for second in seconds
for third in thirds
for fourth in fourths
for fifth in fifths
for sixth in sixths
for seventh in sevenths
for eighth in eighths]
However it keeps showing a SyntaxError: invalid syntax after the for and now I have absolutely no idea how to make this work. If possible please look into this for me, thank you so much!
So the magic function you need to know about to pick a random letter is random.choice. You can pass a list into this function and it will give you a random element from that list. It also works with strings because strings are basically a list of chars. Also to make your life easier, use string module. string.ascii_lowercase returns all the letters from a to z in a string so you don't have to type it out. Lastly, you don't use loops to join strings together. Keep it simple. You can just add them together.
import string
from random import choice
first = 'A'
second = choice(string.ascii_lowercase)
third = choice(string.ascii_lowercase)
fourth = choice(string.ascii_lowercase)
fifth = choice("aeiou")
sixthSeventh = choice(string.ascii_lowercase)
eighth = choice("eiou")
word = first + second + third + fourth + fifth + sixthSeventh + sixthSeventh + eighth
print(word)
Try this:
import random
sixth=random.choice(sixths)
s='A'+random.choice(seconds)+random.choice(thirds)+random.choice(fourths)+random.choice(fifths)+sixth+sixth+random.choice(eighths)
print(s)
Output:
Awixonno
Ahiwojjy
etc
There are several things to consider. First, the str.join() method takes in an iterable (e.g. a list), not a bunch of individual elements. Doing
''.join([first, second, third, fourth, fifth])
fixes the program in this respect. If you are using Python 3, print() is a function, and so you should add parentheses around the entire list comprehension.
With the syntax out of the way, let's get to a more interesting problem: Your program constructs every (82255680 !) possible word. This takes a long time and memory. What you want is probably to just pick one. You can of course do this by first constructing all, then picking one at random. It's far cheaper though to pick one letter from each of firsts, seconds, etc. at random and then collecting these. All together then:
import random
firsts = ['A']
seconds = ['a','b','c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
thirds = ['a', 'e', 'i', 'o', 'u', 'y']
fourths = ['a','b','c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
fifths = ['a', 'e', 'i', 'o', 'u', 'y']
sixths = sevenths = ['a','b','c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
eighths = ['e', 'i', 'o', 'u', 'y']
result = ''.join([
random.choice(firsts),
random.choice(seconds),
random.choice(thirds),
random.choice(fourths),
random.choice(fifths),
random.choice(sixths),
random.choice(sevenths),
random.choice(eighths),
])
print(result)
To improve the code from here, try to:
Find a way to generate the "data" in a neater way than writing it out explicitly. As an example:
import string
seconds = list(string.ascii_lowercase) # you don't even need list()!
Instead of having a separate variable firsts, seconds, etc., collect these into a single variable, e.g. a single list containing each original list as a single str with all characters included.
This will implement what you describe. You can make the code neater by putting the choices into an overall list rather than have several different variables, but you will have to explicitly deal with the fact that the sixth and seventh letters are the same; they will not be guaranteed to be the same simply because there are the same choices available for each of them.
The list choices_list could contain sub-lists per your original code, but as you are choosing single characters it will work equally with strings when using random.choice and this also makes the code a bit neater.
import random
choices_list = [
'A',
'abcdefghijklmnopqrstuvwxyz',
'aeiouy',
'abcdefghijklmnopqrstuvwxyz',
'aeiouy',
'abcdefghijklmnopqrstuvwxyz',
'eiouy'
]
letters = [random.choice(choices) for choices in choices_list]
word = ''.join(letters[:6] + letters[5:]) # here the 6th letter gets repeated
print(word)
Some example outputs:
Alaeovve
Aievellu
Ategiwwo
Aeuzykko
Here's the syntax fix:
print(["".join([first, second, third])
for first in firsts
for second in seconds
for third in thirds])
This method might take up a lot of memory.

Check if a string is in a list of letters - Python3

I have this list which contains letters, and I need to check if a pre-determined word located in another list is horizontally inside this list of letters.
i.e.:
mat_input = [['v', 'e', 'd', 'j', 'n', 'a', 'e', 'o'], ['i', 'p', 'y', 't', 'h', 'o', 'n', 'u'], ['s', 'u', 'e', 'w', 'e', 't', 'a', 'e']]
words_to_search = ['python', 'fox']
I don't need to tell if a word was not found, but if it was I need to tell which one.
My problem is that so far I've tried to compare letter by letter, in a loop similar to this:
for i in range(n): # n = number of words
for j in range(len(word_to_search[i])): # size of the word I'm searching
for k in range(h): # h = height of crossword
for m in range(l): # l = lenght of crossword
But it's not working, inside the last loop I tried several if/else conditions to tell if the whole word was found. How can I solve this?
You can use str.join:
mat_input = [['v', 'e', 'd', 'j', 'n', 'a', 'e', 'o'], ['i', 'p', 'y', 't', 'h', 'o', 'n', 'u'], ['s', 'u', 'e', 'w', 'e', 't', 'a', 'e']]
words_to_search = ['python', 'fox']
joined_input = list(map(''.join, mat_input))
results = {i:any(i in b or i in b[::-1] for b in joined_input) for i in words_to_search}
Output:
{'python': True, 'fox': False}
I'd start by joining each sublist in mat_input into one string:
mat_input_joined = [''.join(x) for x in mat_input]
Then loop over your words to search and simply use the in operator to see if the word is contained in each string:
for word_to_search in words_to_search:
result = [word_to_search in x for x in mat_input_joined]
print('Word:',word_to_search,'found in indices:',[i for i, x in enumerate(result) if x])
Result:
Word: python found in indices: [1]
Word: fox found in indices: []

Sorting a list using an alphabet string

I'm trying to sort a list containing only lower case letters by using the string :
alphabet = "abcdefghijklmnopqrstuvwxyz".
that is without using sort, and with O(n) complexity only.
I got here:
def sort_char_list(lst):
alphabet = "abcdefghijklmnopqrstuvwxyz"
new_list = []
length = len(lst)
for i in range(length):
new_list.insert(alphabet.index(lst[i]),lst[i])
print (new_list)
return new_list
for this input :
m = list("emabrgtjh")
I get this:
['e']
['e', 'm']
['a', 'e', 'm']
['a', 'b', 'e', 'm']
['a', 'b', 'e', 'm', 'r']
['a', 'b', 'e', 'm', 'r', 'g']
['a', 'b', 'e', 'm', 'r', 'g', 't']
['a', 'b', 'e', 'm', 'r', 'g', 't', 'j']
['a', 'b', 'e', 'm', 'r', 'g', 't', 'h', 'j']
['a', 'b', 'e', 'm', 'r', 'g', 't', 'h', 'j']
looks like something goes wrong along the way, and I can't seem to understand why.. if anyone can please enlighten me that would be great.
You are looking for a bucket sort. Here:
def sort_char_list(lst):
alphabet = "abcdefghijklmnopqrstuvwxyz"
# Here, create the 26 buckets
new_list = [''] * len(alphabet)
for letter in lst:
# This is the bucket index
# You could use `ord(letter) - ord('a')` in this specific case, but it is not mandatory
index = alphabet.index(letter)
new_list[index] += letter
# Assemble the buckets
return ''.join(new_list)
As for complexity, since alphabet is a pre-defined fixed-size string, searching a letter in it is requires at most 26 operations, which qualifies as O(1). The overall complexity is therefore O(n)

How to find how many times a word appears in a array? Python [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
item frequency count in python
Quick question
How do you find how many times a word appears in an array?
I have an array that has around 5000 words of text, and i want to find how many times the word "help" appears in the array. How do i do this?
the array is stored in x, so my code looks like this:
x = [...]
word = "help"
and then i dont know what to put to get the number of times "help" appears in x
thank you for any help!
>>> import collections
>>> print collections.Counter(['a', 'word', 'is', 'a', 'thing', 'that', 'is', 'countable'])
Counter({'a': 2, 'is': 2, 'word': 1, 'that': 1, 'countable': 1, 'thing': 1})
This is 2.7+, a Counter.
Based on your edit, where each element in the list is a letter instead of the full word, then:
>>> import re
>>> letters =
['i', 'n', 'e', 'e', 'd', 's', 'o', 'm', 'e', 'h', 'e', 'l', 'p', 'h', 'e', 'l', 'p', 'm', 'e', 'p', 'l', 'e', 'a', 's', 'e', 'I', 'n', 'e', 'e', 'd', 'h', 'e', 'l', 'p']
>>> len(re.findall('help', "".join(letters)))
3
As #sberry has depicted, Counter would server the purpose, but in case you are only searching a single word once and not interested to get the occurrence of all the words, you can use a simpler tool for the purpose
(I have taken the example from sberry)
Given a list of words to find the occurrence of any given words, you can use the count method of the list
>>> list_of_words=['a', 'word', 'is', 'a', 'thing', 'that', 'is', 'countable']
>>> list_of_words.count('is')
2
As your comments have shown you may be interested to search on a list of characters. Such as
letters =
['i', 'n', 'e', 'e', 'd', 's', 'o', 'm', 'e', 'h', 'e', 'l', 'p', 'h', 'e', 'l', 'p', 'm', 'e', 'p', 'l', 'e', 'a', 's', 'e', 'I', 'n', 'e', 'e', 'd', 'h', 'e', 'l', 'p']
You can also use the count on the string after is generated by concatenating all the characters
>>> ''.join(letters).count('help')
3
In case the words are jumbled, collections.Counter ad do magic here
>>> def count_words_in_jumbled(jumbled,word):
jumbled_counter = collections.Counter(jumbled)
word_counter = collections.Counter(word)
return min(v /word_counter[k] for k,v in jumbled_counter.iteritems() if k in word)
>>> count_words_in_jumbled(['h','e','l','l','h','e','l','l','h','e','l'],'hel')
3
>>> count_words_in_jumbled(['h','e','l','l','h','e','l','l','h','e','l'],'hell')
2
>>> count_words_in_jumbled(['h','x','e','y','l','u','p'] ,'help')
1
nhelps = len(''.join(charlist).split('help')[1:]

Categories

Resources