def bestInvitation(first, second):
yeah=tuple(zip(first, second))
res=list(set.intersection(*map(set, yeah)))
common=str(res)
count=0
for i in yeah:
if common in i:
count+=1
return count
if __name__ == '__main__':
print(bestInvitation(["fishing", "gardening", "swimming", "fishing"],
["hunting", "fishing", "fishing", "biting"]))
In the code above, line 6 should find the number of times that the common element between the 4 pairs of activities. This example should return 4 because fishing is a common element which occurs 4 times. However, it is returning 0. I think it's because common is not just a string, but a list of one string, but I don't know how to turn res into just a string. Any recommendations?
A simple print statement makes the problem clear:
...
for i in yeah:
print(common, i)
if common in i:
...
Output:
['fishing'] ('fishing', 'hunting')
['fishing'] ('gardening', 'fishing')
['fishing'] ('swimming', 'fishing')
['fishing'] ('fishing', 'biting')
You did not search for a string in a tuple of strings: you search for a string image of a list containing a string within your tuple. Since there is no such entity inside your tuple, the if statement fails on every iteration.
Fix your data handling -- one line:
common=str(res[0])
Now you get the desired output of 4.
Related
I have a nested expression as below
expression = 'position(\'a\' IN Concat("function_test"."PRODUCT_CATEGORIES"."CATEGORY_NAME" , "function_test"."PRODUCT_CATEGORIES"."CATEGORY_NAME" ))'
I want the output as by retreiving nested function first and then outer functions
['Concat("function_test"."PRODUCT_CATEGORIES"."CATEGORY_NAME" , "function_test"."PRODUCT_CATEGORIES"."CATEGORY_NAME" )','position(\'a\' IN Concat("function_test"."PRODUCT_CATEGORIES"."CATEGORY_NAME" , "function_test"."PRODUCT_CATEGORIES"."CATEGORY_NAME" ))']
Below is the code I have tried
result = []
for i in range(len(expression)):
if expression[i]=="(":
a.append(i)
elif expression[i]==")":
fromIdx=a.pop()
fromIdx2=max(a[-1],expression.rfind(",", 0, fromIdx))
flag=False
for (fromIndex, toIndex) in first_Index:
if fromIdx2 + 1 >= fromIndex and i <= toIndex:
flag=True
break
if flag==False:
result.append(expression[fromIdx2+1:i+1])
But this works only if expression is separated by ','
for ex:
expression = 'position(\'a\' , Concat("function_test"."PRODUCT_CATEGORIES"."CATEGORY_NAME" , "function_test"."PRODUCT_CATEGORIES"."CATEGORY_NAME" ))'
and result for this expression from my code will be correct as exprected.
In first expression ,I mentioned ,there is IN operator instead of ',' hence my code doesnt work.
Please help
If you want it to be reliable, you need a full-fledged SQL parser. Fortunately, there is an out-of-box solution for that: https://pypi.org/project/sqlparse/. As soon as you have a parsed token tree, you can walk through it and do what you need:
import sqlparse
def extract_functions(tree):
res = []
def visit(token):
if token.is_group:
for child in token.tokens:
visit(child)
if isinstance(token, sqlparse.sql.Function):
res.append(token.value)
visit(tree)
return res
extract_functions(sqlparse.parse(expression)[0])
Explanation.
sqlparse.parse(expression) parses the string and returns a tuple of statements. As there is only one statement in the example, we can just take the first element. If there are many statements, you should rather iterate over all tuple elements.
extract_functions recursively walks over a parsed token tree depth first (since you want inner calls appear before outer ones) using token.is_group to determine if the current token is a leaf, tests if the current token is a function, and if it is, appends its string representation (token.value) to the result list.
I have two lists which contain the following type of information.
List #1:
Request_List = ["1/1/1.34", "1/2/1.3.5", "1/3/1.2.3", ...same format elements]
List #2:
Reply_List = ["1/1/0", "1/3/1", "1/2/0", ...same format elements]
From the "Reply" list, I want to be able to compare the second item in the "#/#/#", in this case it will be 1,3,2, and so on with all the items in the Reply list and check if there is a match with the second item in "Request list". If there is a match, then I want to be able to return a new list which would contain the information of the third index in the request string appended with the third index of the matching string in the reply.
The result would be like the following.
Result = ["1.34.0", "1.3.5.0", "1.2.3.1"]
Note that the 0 was appended to the 1.34, the 1 was appended to the 1.3.4 and the 0 was appended to the 1.2.3 from the corresponding indexes in the "Reply" list as the second index existed in the "Reply" list. The 'Reply" list could have the item anywhere placed in the list.
The code which does the problem stated above is shown below.
def get_list_of_error_codes(self, Reply_List , Request_List ):
decoded_Reply_List = Reply_List .decode("utf-8") # I am not sure if this is
the right way to decode all the elements in the list?
Result = [
f"{i.split('/')[-1]}.{j.split('/')[-1]}"
for i in Request_List
for j in decoded_Reply_List
if (i.split("/")[1] == j.split("/")[1])
]
return Result
res = get_list_of_error_codes(Reply_List , Request_List)
print (res) # ["1.34.0", "1.3.5.0", "1.2.3.1"]
Issues I am facing right now:
I am NOT sure if I decode the Reply_List correctly and in the proper manner. Can someone help me also verify this?
I am not sure on how to also remove the corresponding items for the Reply_List and Request_List when I find a match based on the condition if (i.split("/")[1] == j.split("/")[1]).
You can use list comprehension to decode the list:
decoded_Reply_List = [li.decode(encoding='utf-8') for li in Reply_List]
In this case, if you wanted to also remove items from the list while you create the new list, I would say list comprehension isn't the right move. Just go with the nested for loops:
def get_list_of_error_codes(self, Reply_List, Request_List):
decoded_Reply_List = [li.decode(encoding='utf-8') for li in Reply_List]
Result = []
for i in list(Request_List):
for j in decoded_Reply_List:
if (i.split("/")[1] == j.split("/")[1]):
Result.append(f"{i.split('/')[-1]}.{j.split('/')[-1]}")
Reply_List.remove(j)
break
else:
continue
Request_List.remove(i)
return Result
Request_List = ["1/1/1.34", "1/2/1.3.5", "1/3/1.2.3"]
Reply_List = [b"1/1/0", b"1/3/1", b"1/2/0"]
print(get_list_of_error_codes("Foo", Reply_List, Request_List))
# Output: ['1.34.0', '1.3.5.0', '1.2.3.1']
Some things to note:
I added a break so that we don't keep looking for matches if we find one. It will only match the first pair, then move on.
In for i in list(Request_List), I added the list() cast to effectively make a copy of the list. This allows us to remove entries from Request_List without disrupting the loop. I didn't do this for for j in decoded_Reply_List because it's already a copy of Reply_List. (I assumed you wanted to remove the entries from Reply_List)
The last is the else: continue. We don't want to reach Request_List.remove(i) if we didn't find a match. If break is called, else will not be called, which means we will reach Request_List.remove(i). But if the loop completes without finding a match, the loop will then enter else and we will skip the removal step by calling continue
EDIT:
Actually, Reply_List.remove(j) breaks, since we've decoded j in this method, thus decoded j is not the same object as it is in Reply_List. Here's some revised code which will solve this issue:
def get_list_of_error_codes(Reply_List, Request_List):
# decoded_Reply_List = [li.decode(encoding='utf-8') for li in Reply_List]
Result = []
for i in list(Request_List):
for j in list(Reply_List):
dj = j.decode(encoding='utf-8')
if (i.split("/")[1] == dj.split("/")[1]):
Result.append(f"{i.split('/')[-1]}.{dj.split('/')[-1]}")
Reply_List.remove(j)
break
else:
continue
Request_List.remove(i)
return Result
Request_List = ["1/1/1.34", "1/2/1.3.5", "1/3/1.2.3"]
Reply_List = [b"1/1/0", b"1/3/1", b"1/2/0"]
print("Result: ", get_list_of_error_codes(Reply_List, Request_List))
print("Reply_List: ", Reply_List)
print("Request_List: ", Request_List)
# Output:
# Result: ['1.34.0', '1.3.5.0', '1.2.3.1']
# Reply_List: []
# Request_List: []
What I've done is that instead of creating a separate decoded list, I just decode the entries as they're looped through, and then remove the un-decoded entry from Reply_List. This should be a little more efficient too, since we're not looping through Reply_List twice now.
Currently i am getting information from an xml file.
If an xml tag has more then one children it will return as a list inside that tag, however if that xml tag has only 1 child it will return not as a list and only as a regular string.
My question is: is there a better way to iterate through this tag? if it is a list, iterate through the list length amount of times, but if it is a string only iterate once?
This is my current approach:
#check if tag is a list, if not then make a list with empty slot at end
if not isinstance(accents['ac'], list):
accents['ac'] = list((accents['ac'], {}))
#loop through guaranteed list
for ac in accents['ac']: #this line throws error if not list object!
#if the empty slot added is encountered at end, break out of loop
if bool(ac) == False:
break
any ideas on how to make this cleaner or more professional is appreciated.
Assuming that the problem is caused by accents['ac'] being either a list of string or a single string, a simple processing could be:
#check if tag is a list, if not then make a list with empty slot at end
if not isinstance(accents['ac'], list):
accents['ac'] = [ accents['ac'] ]
#loop through guaranteed list
for ac in accents['ac']: #this line throws error if not list object!
...
For readabilities sake, it might be better to do
if isinstance(accents['ac'], str):
pass #insert what you want to happen here when it is a string
else:
for(ac in accents['ac']):
pass #insert what you want to happen here when it is a list
suppposing that i want to add them to a list, i would check if its a nested tag first then add them.
tag_list=[]
if(len(accents['ac'])>1):
for tag in accents['ac']:
tag_list.append(tag)
else:
tag_list.append(tag)
I am trying to make a python program that takes user input text or a file and changes each character into a value and then returns the result.
I have a user string that being read into a list.
I am trying to have a for loop go through that list and check each character against a dictionary key and then return the value in the dictionary. How would i go about doing that?
Thanks
Code so far:
for i in range (0, len(text)):
for j in alphabet.keys():
if text[i].upper() == alphabet.values():
j+=1
print(alphabet.items())
i+=1
for item in list_:
try:
print(d[item])
except KeyError as e:
print("{} not in d".format(e.args[0]))
Without seeing your code, I can't offer anything more relevant
You probably want to use string.maketrans and string.translate
>>> import string
>>> table = string.maketrans('abc', 'xyz')
>>> string.translate('the cat is bad', table)
'the zxt is yxd'
Most of the code below is simply to create the dictionary that translates letters of an input into randomised corresponding values in a dict (i.e. each letter maps to another random letter). Points on your code:
1) range() automatically defaults to starting at 0 so range(0, n) is better just written as range(n)
2) You don't need to use range() at all here. for letter in string will take an input string and go through it, letter by letter. for elephant in string will do the same, each letter is being assigned to the name elephant in turn, so the fact that I chose to use letter instead is simply for readability.
3) Using keys(), values() and items() is not the way to query a dictionary. You have two standard approaches; I could use translation_dict[letter] which will throw KeyError if the value of letter is not a key in the dictionary, or translation_dict.get(letter) which will return None if the key doesn't exist. In the below example, I used get() but also added another parameter ("not in dict") which replaces None as the default value if the letter isn't found as a key.
import string # For setup of example data
import random # For setup of example data
# Just creating the translation dictionary and fake user input
alphabet = list(string.uppercase)
translated = random.sample(alphabet, len(alphabet))
translation_dict = {i: j for i, j in zip(alphabet, translated)}
user_input = 'Hello'
# The loop you're trying
for letter in user_input:
corresponding_value = translation_dict.get(letter.upper(), 'Not in dict')
print(corresponding_value)
I'm trying to implement a postscript interpreter in python. For this part of the program, I'm trying to access multiple occurrences of the same element in a list, but the function call does not do that. I can explain it better with the code.
This loop steps through a list of tokens
for token in tokens:
process_token(token)
tokens is define as:
line = "/three 3 def /four 4 def"
tokens = line.strip().split(" ")
So after this is done tokens looks like ['/three', '3', 'def', '/four', '4', 'def'].
Process tokens will continue to push thing on to a stack until it reaches an operation to be done, in this case def. Once it gets to def it will execute:
if (t == "def"):
handle_def (tokens.index(t)-2, tokens.index(t)-1)
stack.pop()
and here is handle_def():
def handle_def (t, t1):
name = tokens[t]
defin = tokens [t1]
x=name[1:]
dict1 [x]= float(defin)
The problem is when it is done adding {'three':3} to the dictionary, it then should keep reading and add {'four':4} to the dictionary. But when handle_def (tokens.index(t)-2, tokens.index(t)-1) is called it will pass in the index numbers for the first occurrence of def, meaning it just puts {'three':3} into the dictionary again. I want it to skip past the first one and go the later occurrences of the word def. How do I make it do that?
Sorry for the long post, but i felt like it needed the explanation.
list.index will give only the first occurrence in the list. You can use the enumerate function to get the index of the current item being processed, like this
for index, token in enumerate(tokens):
process_token(index, token)
...
...
def process_token(index, t):
...
if t == "def":
handle_def (index - 2, index - 1)
...