Yield a list of matching elements from 2 different lists - python

I have a (somewhat long) list of words. And a function 1 (linsok(lista, elem)) which asks the user for a word, and if the user-inputted word exists in the list, we get a confirmation in the form of exists/does not exist.
I then have a 2nd function which for any word in the list will create 4 variations of it (creating 4 concatenations of each word) and append these new words to another list. This function will come in handy in my third function, which I am having trouble constructing.
My third function will compare the words in my original list, to the list of my concatenated words. If any word in the concatenated list exists in my orginal list, the function should yield these matches in a list (in the form of [original word, concatenated word] where both are present in the original list). All with the caveat that this third function is to include a function call for the 1st function which asks for user input of a word and produces a confirmation of the word's existence.
I have tried to write the function in the form of for item1 in list 2 and for item2 in list 2 but honestly in pretty lost as to how to construct the function. Especially how/where I am to insert my function call to the first function.
This is the code as it stands now:
`
########## UPPGIFT 1 ##########
#fil = open('ordlista.txt')
lista = open('ordlista.txt').read().split()
#print(lista[::100])
########## UPPGIFT 2 #########
def linsok(lista, elem): #function 1 which returns whether or not a word is present in list
if elem in lista:
print(elem + ' exists')
return True
else:
print(elem + ' exists not')
return False
########## UPPGIFT 3 ##########
def kupering(ord): #function which concatenates the words in question
nylista = []
if ord in lista:
for i in range(len(ord)):
nylista.append((ord[i:len(ord)] + ord[:i]))
#nylista=nylista[1:]
#print(nylista)
return nylista
#def linsok_kup(lista): #funtion 3 which i have trouble with
# def main():
# while elem := input('Ditt ord: '):
# linsok(lista,elem) #u2
#
# #where i would insert my 3rd function
#
# if __name__ == '__main__':
# main()
`

Your explanation is a little unclear but here goes.
Assuming concantenation as in your function is correct.
cat -> [(catc),(catca),(catcat)]
You can simply use a dict to save a lot of time.
def kupering(ord,mydict):
nylista = []
if ord in lista:
for i in range(min(len(ord),3)):
nylista.append(ord[i:len(ord)] + ord[:i])
try:
mydict[ord[i:len(ord)] + ord[:i]].append(ord) #child has not been made before
except:
mydict[ord[i:len(ord)] + ord[:i]] = [ord] #concantenated word has been made before
return nylista, mydict #we return your 'list' and also our 'dict of children and their parents'
The dict now contains all your 'root' words and their children.
This then forces the condition that if the child exists, yield result IFF parent exists.
def new_function(user_input, mydict,lista):
test = linsok(user_input,lista) #use your function to see if word exist
if test == True:
#I guess we want if this is true
eval = mydict[user_input]
if len(eval)==0: #Case were it doesnt exist in 'concantenated words"
print("I do not exist in children")
return None #leave the fucntion with nothing
outputs = []
for word in eval: #alternate case is if it does exist
result = linsok(lista,word) #do parent of word exist in lista
if result == True:
print([eval,user_input]) #if yes we add to our outputs
output.append([eval,user_input])
return output
else:
return None
#Covers scenario where a child can have multiple parents I think. abab -> ababa,ababab... , aba -> abab, ababa,ababab....

From your description, I'm not sure what the result of linsok() in the third functions is used for.
I also assume that all the words in lista are at least four characters long, since a word with less than four characters would not give 4 variations.
lista = ["hello", "dogs", "cars", "scar"]
concact_lst = kupering("cars")
def third_func(concact_lst):
user_input = input("Enter word: ")
word_exists = linsok(lista, user_input)
result = []
for i in range(len(concact_lst)):
for j in range(len(lista)):
if concact_lst[i] == lista[j]:
result.append([lista[j], concact_lst[i]])
return result
print(third_func(concact_lst))
output: [['cars', 'cars'], ['scar', 'scar']]

Related

I want to find the first, second, and last words in a string

Given a string, I want to write 3 separate functions:
first_word is to print the first word of the string
second_word is to print the second word of the string
last_word is to print the last word of the string
If the string has 2 words in total, the output from function 2 should be equal to function 3.
Example:
sentence = "once upon a time there was a programmer"
print(first_word(sentence)) # once
print(second_word(sentence)) # upon
print(last_word(sentence)) # programmer
What I tried so far:
def first_word(str):
space = str.find(' ')
return(str[0:space])
sentence = "once upon a time there was a programmer"
print(first_word(sentence))
Output:
once
What I'm stuck on:
I'm not sure how to do the second and third functions. Is there a way to have function 1 incorporated into function 2 and 3? Then the only difference between the 3 functions is that they're different iterations of function 1. Please explain your thought process as well.
use :
def finder(str, value):
space = str.split(' ')
if value == "first":
return space[0]
elif value == "second":
return space[1]
elif value == "last":
return space[-1]
sentence = "once upon a time there was a programmer"
print(finder(sentence, "first"))
print(finder(sentence, "second"))
print(finder(sentence, "last"))
You can form a list of all the strings in the given sentence and the use the corresponding indices to get the word you want as demonstrated below
class Word_Finder:
def __init__(self,sentence):
self.sentence = sentence
self.word_list = self.sentence.split() #splits the sentence
def first_word(self):
return self.word_list[0]
def second_word(self):
return self.word_list[1]
def last_word(self):
return self.word_list[-1]
sentence = "once upon a time there was a programmer"
words = Word_Finder(sentence)
print(words.first_word())
print(words.second_word())
print(words.last_word())
Here , I am assuming that your sentence will always have 2 or more words.
To lessen the bloat of using def functions, we could use a simple lambda function that uses the split() operation.
This may look something like this:
sentence = "once upon a time there was a programmer"
find_word = lambda index: sentence.split(" ")[index]
find_word can now be given any arbitrary index to list any word you may want.
find_word(0) # returns 'once'
find_word(1) # returns 'upon'
find_word(-1) # returns 'programmer'
A def function implementation would be:
def find_word(sentence, index) -> String:
# except when index is outside of sentence length
try:
return sentence.split(" ")[index]
except IndexError:
return ""
You can use string split method to get words from your sentence https://www.w3schools.com/python/ref_string_split.asp
#!/usr/bin/env python3
# coding=utf-8
sentence = 'once upon a time there was a programmer'
def get_words(input):
return input.split(" ")
def first_word(data):
words = get_words(data)
if len(words) != 0:
print(f"First word = {words[0]}")
def second_word(data):
words = get_words(data)
if len(words) > 1:
print(f"Second word = {words[1]}")
else:
print("Second word = Null")
def last_word(data):
words = get_words(data)
if len(words) != 0:
print(f"Last word = {words[-1]}")
if __name__ == "__main__":
first_word(sentence)
second_word(sentence)
last_word(sentence)

Str to int function

I am supposed to write a function that lets the user put in any string of numbers and then turns that input into an int list (e.g "12635 1657 132651627"). However, I don't know how to change this bit of code so that the user can actually put something into the console. When I try to introduce a new variable Python says that there is no value assigned to it, and I do not know how to work around that. I want everything to be within the function. I managed to introduce a new variable before the start of the function but that's not really my aim here.
def Int_Split(a):
List = []
last = 0
max = len(a)
for i in range (max):
if a[i] =="":
nmbr = a[last:i]
last = i+1
List.append(int(nbmr))
nmbr = a[last:]
List.append(int(nmbr))
return List
print(List)
It isn't clear what your issue is with adding a variable, or entirely what you're after. But if you are after converting "12635 1657 132651627" to [12635, 1657, 132651627], that can be done very simply with:
s = "12635 1657 132651627"
l = [int(x) for x in s.split()]
print(l)
Which yields:
[12635, 1657, 132651627]
Here is an example in a function:
def main():
print("input some numbers:")
s = input()
print([int(x) for x in s.split()])
if __name__ == "__main__":
main()
Here we print the request for input, set the value given to s, then use a list comprehension to say: split a string on any whitespace, then give the integer value for each.
Here is a method without using string.split():
def sep(s):
words = []
word = ""
for c in s:
if c != " ":
word += c
continue
words.append(word)
word = ""
else:
words.append(word)
return words
def main():
print("input some numbers:")
s = input()
print([int(x) for x in sep(s)])
if __name__ == "__main__":
main()
Here we have written a function called sep, which just iterates over characters in the given string until it finds a space or the end, each time adding that group of characters to a list of strings.

why i am getting double the frequency count of vowels?

So i was solving a question that is in my Lab practical Syllabus. Below is the question:-
Write a python class to reverse a sentence (initialized via
constructor) word by word. Example: “I am here” should be reversed as
“here am I”. Create instances of this class for each of the three
strings input by the user and display the reversed string for each, in
descending order of number of vowels in the string.
Below is code for the implementation of above question:-
class sentenceReverser:
vowels = ['a','e','i','o','u']
vowelCount =0
sentence=""
reversed_string = ""
def __init__(self,sentence):
self.sentence = sentence
self.reverser()
def reverser(self):
self.reversed_string = " ".join(reversed(self.sentence.split()))
return self.reversed_string
def getVowelCount(self):
for i in self.sentence:
if i.lower() in self.vowels:
self.vowelCount += 1
return self.vowelCount
inp = []
for i in range(2):
temp = input("Enter string:- ")
ob = sentenceReverser(temp)
inp.append(ob)
sorted_item = sorted(inp,key = lambda inp:inp.getVowelCount(),reverse=True)
for i in range (len(sorted_item)):
print('Reversed String: ',sorted_item[i].reverser(),'Vowel count: ',sorted_item[i].getVowelCount())
Below is output i am getting for the above code:-
issue:-
Could someone tell me why i am getting double the vowel count???
Any help would be appreciated!!
You are calling getVowelCount() twice. Instead you can use the variable instead of calling in the print command
for i in range (len(sorted_item)):
print('Reversed String: ',sorted_item[i].reverser(),'Vowel count: ',sorted_item[i].vowelCount)
This is because you don't reset vowel count in the method. So if you execute the method once (here in sort), you'll get correct count. If you execute it twice (in printing), you will get twice as much. If you execute it once more, you'll get 3x correct amount. And so on.
The solution is to reset the number:
def getVowelCount(self):
self.vowelCount = 0
for i in self.sentence:
if i.lower() in self.vowels:
self.vowelCount += 1
return self.vowelCount
Or to calculate it only once - set it to None, then calculate only if self.vowelCount is None, otherwise return existing value.

Binary Search using a for loop, searching for words in a list and comparing

I'm trying to compare the words in "alice_list" to "dictionary_list", and if a word isnt found in the "dictionary_list" to print it and say it is probably misspelled. I'm having issues where its not printing anything if its not found, maybe you guys could help me out. I have the "alice_list" being appended to uppercase, as the "dictionary_list" is all in capitals. Any help with why its not working would be appreciated as I'm about to pull my hair out over it!
import re
# This function takes in a line of text and returns
# a list of words in the line.
def split_line(line):
return re.findall('[A-Za-z]+(?:\'[A-Za-z]+)?', line)
# --- Read in a file from disk and put it in an array.
dictionary_list = []
alice_list = []
misspelled_words = []
for line in open("dictionary.txt"):
line = line.strip()
dictionary_list.extend(split_line(line))
for line in open("AliceInWonderLand200.txt"):
line = line.strip()
alice_list.extend(split_line(line.upper()))
def searching(word, wordList):
first = 0
last = len(wordList) - 1
found = False
while first <= last and not found:
middle = (first + last)//2
if wordList[middle] == word:
found = True
else:
if word < wordList[middle]:
last = middle - 1
else:
first = middle + 1
return found
for word in alice_list:
searching(word, dictionary_list)
--------- EDITED CODE THAT WORKED ----------
Updated a few things if anyone has the same issue, and used "for word not in" to double check what was being outputted in the search.
"""-----Binary Search-----"""
# search for word, if the word is searched higher than list length, print
words = alice_list
for word in alice_list:
first = 0
last = len(dictionary_list) - 1
found = False
while first <= last and not found:
middle = (first + last) // 2
if dictionary_list[middle] == word:
found = True
else:
if word < dictionary_list[middle]:
last = middle - 1
else:
first = middle + 1
if word > dictionary_list[last]:
print("NEW:", word)
# checking to make sure words match
for word in alice_list:
if word not in dictionary_list:
print(word)
Your function split_line() returns a list. You then take the output of the function and append it to the dictionary list, which means each entry in the dictionary is a list of words rather than a single word. The quick fix it to use extend instead of append.
dictionary_list.extend(split_line(line))
A set might be a better choice than a list here, then you wouldn't need the binary search.
--EDIT--
To print words not in the list, just filter the list based on whether your function returns False. Something like:
notfound = [word for word in alice_list if not searching(word, dictionary_list)]
Are you required to use binary search for this program? Python has this handy operator called "in". Given an element as the first operand and and a list/set/dictionary/tuple as the second, it returns True if that element is in the structure, and false if it is not.
Examples:
1 in [1, 2, 3, 4] -> True
"APPLE" in ["HELLO", "WORLD"] -> False
So, for your case, most of the script can be simplified to:
for word in alice_list:
if word not in dictionary_list:
print(word)
This will print each word that is not in the dictionary list.

Reference next item in list: python

I'm making a variation of Codecademy's pyglatin.py to make a translator that accepts and translates multiple words. However, I'm having trouble translating more than one word. I've been able to transfer the raw input into a list and translate the first, but I do not know how to reference the next item in the list. Any help would be greatly appreciated.
def piglatin1():
pig = 'ay'
original = raw_input('Enter a phrase:').split(' ')
L = list(original)
print L
i = iter(L)
item = i.next()
for item in L:
if len(item) > 0 and item.isalpha():
word = item.lower()
first = word
if first == "a" or first == "e" or first == "i" or first == "o" or first =="u":
new_word = word + pig
print new_word
else:
new_word = word[1:] + word[0:1] + pig
# first word translated
L = []
M = L[:]
L.append(new_word)
print L # secondary list created.
again = raw_input('Translate again? Y/N')
print again
if len(again) > 0 and again.isalpha():
second_word = again.lower()
if second_word == "y":
return piglatin()
else:
print "Okay Dokey!"
else:
print 'Letters only please!'
return piglatin1()
I was working on this problem recently as well and came up with the following solution (rather than use range, use enumerate to get the index).
for index, item in enumerate(L):
next = index + 1
if next < len(L):
print index, item, next
This example shows how to access the current index, the current item, and then the next item in the list (if it exists in the bounds of the list).
Here are a few things to note that might help.
The lines i = iter(L) and item = i.next() are unnecessary. They have no effect in this method because you are redefining item immediately afterwards in the line for item in L. Go ahead and comment out those two lines to see if it makes any changes in your output.
The looping construct for item in L will go once over every item in the list. Whatever code you write within this loop will be executed once for each item in the list. The variable item is your handle to the list element of an iteration.
If, during any iteration, you really do want to access the "next" element in the list as well, then consider using a looping construct such as for i in range(0,len(L)). Then L[i] will be the current item and L[i+1] will you give the subsequent item.
There are some slight issues with the code but I think there is one main reason why it will not repeat.
In order to process the entire string the
again = raw_input('Translate again? Y/N')
and it's succeeding lines should be brought outside the for statement.
Also you appear to be setting L to an empty string inside the loop:
L = []
The following is a modified version of your code which will loop through the entire sentence and then ask for another one.
def piglatin():
pig = 'ay'
while True:
L = raw_input('Enter a phrase:').split(' ')
M = []
for item in L:
if len(item) > 0 and item.isalpha():
word = item.lower()
first = word
if first == "a" or first == "e" or first == "i" or first == "o" or first =="u":
new_word = word + pig
print new_word
else:
new_word = word[1:] + word[0:1] + pig
M.append(new_word)
else:
print 'Letters only please!'
print M # secondary list created.
again = raw_input('Translate again? Y/N')
print again
if len(again) > 0 and again.isalpha():
second_word = again.lower()
if second_word == "n":
print "Okay Dokey!"
break
Changes made:
You don't need to cast the return of the split to a list. The split
return type is a list.
It isn't necessary to make an iterator, the for loop will do this for you.
I removed the function as the return type. I'm assuming you were attempting some form of recursion but it isn't strictly necessary.
Hope this helps.
Step by step:
If you set variable original in this way:
original = raw_input('Enter a phrase:').split()
it will be already a list, so need to additional assignment.
What is the purpose of these lines?
i = iter(L)
item = i.next()
In a loop, you assign variable to the word, when it is actually only the first letter of the word, so it’ll be better like this: first = word[0]
Then if you want to check if first is a vowel, you can just do:
if first in 'aeuoiy'
Answer to your actual question: do not assign L to an empty list!
If you want to repeat the action of a function, you can just call it again, no need to rewrite the code.

Categories

Resources