Currently learning python. Normally a C++ guy.
if wallpaper == "Y":
charge = (70)
print ("You would be charged £70")
wallpaperList.append(charge)
elif wallpaper == "N" :
charge = (0)
else:
wallPaper ()
surfaceArea
totalPapers = 0
for item in range (len(wallpaperList)):
totalPapers += wallpaperList[item]
I am trying do a for loop for the if statement.
In c++ this will just be a simple
for (I=0; i<pRooms; i++){
}
I am trying to add the above code in a for loop but I seem to fail.
Thanks
Python loops iterate over everything in the iterable:
for item in wallpaperList:
totalPapers += item
In modern C++, this is analogous to:
std::vector<unsigned int> wallpaperList;
// ...
for(auto item: wallpaperList) {
totalPapers += item
}
You could also just use the sum function:
cost = sum(wallpaperList)
If the charge is 70 every time, why not just do multiplication?
while wallPaper == 'Y':
# ...
# Another satisfied customer!
i += 1
cost = i * 70
For the exact equivalent of your for loop, use range:
for (i=0; i<pRooms; i++){ # C, C++
}
for i in range(pRooms): # Python
...
Both loops iterate over the values 0 to pRooms-1. But python gives you other options. You can iterate over the elements of the list without using an index:
for room in listOfRooms:
if room.wallpaper == "Y":
...
List comprehensions are also nice. If you don't care about the print calls in your code, you could compute the cost in one line with something like this:
totalPapers = sum(70 for room in listOfRooms if room.wallpaper == "Y")
Related
Let's say I have the dict below
{
"1": {
"rarity": 1
},
"2": {
"rarity": 2
}
}
and I want to find the amount of times rarity is 1. Instead of doing
count = 0
for x in dict.values():
if x['rarity'] == 1:
count += 1
return count
Is there a better way to do this? I found this post about using map, but I'm not sure how to get it to work with a nested dictionary.
You can write it much shorter:
count = sum(v["rarity"] == 1 for v in d.values())
from rioV8's comment, with inspiration from Mateen Ulhaq's comment
You can use the following helper function with the map.
def functionHelper(value):
if value["rarity"] == 1:
return 1
return 0
sum(map(functionHelper, d.values()))
or you can use one of these:
sum(map((1).__eq__, [v["rarity"] for v in d.values()]))
sum(v["rarity"] == 1 for v in d.values())
Alright. I have seen quite a few questions like this on StackOverflow, but none really helped me. I am working on a python script that moves some base32 code around. Here is the problematic function:
def getCode():
i = 0
j = 0
k = 0
base32 = input("Please paste your code below:\n")
base32 = base32.split("#")
while i < len(base32):
base32[i] = base32[i].split(",")
i += 1
while j < len(base32[i]):
base32[i[j]] = base32[i[j]].split(" ")
j += 1
while k < len(base32[i[j]]):
if base32[i[[j[k]]]] == "":
base32.list_splice(k, 1)
k += 1
if base32[i[j]].len() == 0:
base32[i].list_splice(j, 1)
return base32
I defined list_splice() earlier. I also declared getCode() after this. When I run it, it asks me for my code, but when I hit enter after, it gives me this:
Traceback (most recent call last):
File "C:\Users\gabri\SynologyDrive\track_mover.py", line 43, in <module>
getCode()
File "C:\Users\gabri\SynologyDrive\track_mover.py", line 32, in getCode
while j < len(base32[i]):
IndexError: list index out of range
I am not sure why. From what I understand, a IndexError generally refers to passing in a list index that is too high, like if you have a string with 3 characters and pass list[3]. I have no idea why it is saying this. I would think that the
while loop would keep it from getting out of hand, but maybe not? I have tried all kinds of lengths of strings that I paste into it, but that doesn't seem to be the answer.
===
EDIT
I tried Mustafa Aydın's answer, and while that does fix some things, it now outputs this:
Traceback (most recent call last):
File "C:\Users\gabri\SynologyDrive\track_mover.py", line 44, in <module>
getCode()
File "C:\Users\gabri\SynologyDrive\track_mover.py", line 33, in getCode
base32[i[j]] = base32[i[j]].split(" ")
TypeError: 'int' object is not subscriptable
I have no idea why it is doing this.
I also got some questions regarding the list_splice() function. What it is is the python equivalent of the javascript .splice() built-in function. Here is the code for it:
def list_splice(target, start, delete_count=None, *items):
"""Remove existing elements and/or add new elements to a list.
target the target list (will be changed)
start index of starting position
delete_count number of items to remove (default: len(target) - start)
*items items to insert at start index
Returns a new list of removed items (or an empty list)
"""
if delete_count == None:
delete_count = len(target) - start
# store removed range in a separate list and replace with *items
total = start + delete_count
removed = target[start:total]
target[start:total] = items
return removed
If it helps any, here is the JavaScript I am converting from:
function loadCode(input) {
var base32 = document.getElementById(input).value;
var base32 = base32.split("#");
for (var i = 0; i < base32.length; i++) {
base32[i] = base32[i].split(",");
for (var j = 0; j < base32[i].length; j++) {
base32[i][j] = base32[i][j].split(" ");
for (var k = 0; k < base32[i][j].length; k++) {
if (base32[i][j][k] == "") {
base32[i][j].splice(k, 1);
}
}
if (base32[i][j].length == 0) {
base32[i].splice(j, 1);
}
}
}
return base32;
}
Thanks in advance for any help!
You should increment i after you are done with the i'th item of the base32 list. Also (response to your edit), accessing a list element in a 2-dimensional fashion is done as base32[i][j] i.e. you first reach to i'th item, then reach to j'th item of that item. Similar applies to base32[i][j][k].
Edit: Seeing your javascript code, I'd say that you should be using for loops in python also. Those will be less error prone. Also, the splicing you are doing (only removing one item) can be done with pop. Lastly, removing elements whilst iterating over a list is not a good idea; one solution is to iterate in reverse order. So, putting all these together, you end up with this:
def getCode():
base32 = input("Please paste your code below:\n")
base32 = base32.split("#")
for i in reversed(range(len(base32))):
base32[i] = base32[i].split(",")
for j in reversed(range(len(base32[i]))):
base32[i][j] = base32[i][j].split(" ")
for k in reversed(range(len(base32[i][j]))):
if base32[i][j][k] == "":
base32[i][j].pop(k)
if len(base32[i][j]) == 0:
base32[i].pop(j)
return base32
while i < len(base32):
base32[i] = base32[i].split(",")
i += 1
while j < len(base32[i]):
On the final iteration of this loop, the loop condition i < len(base32) is still true, so the loop executes one last time. But then i is incremented inside the loop, so now base32[i] is out-of-bounds.
Generally, incrementing a loop variable should be done at the bottom of the loop, so that no code executes with a possibly-too-large value of the loop variable.
I have a dictionary where the key is a string and the values of the key are a set of strings that also contain the key (word chaining). I'm having trouble finding the max depth of a graph, which would be the set with the most elements in the dictionary, and I'm try print out that max graph as well.
Right now my code prints:
{'DOG': [],
'HIPPOPOTIMUS': [],
'POT': ['SUPERPOT', 'HIPPOPOTIMUS'],
'SUPERPOT': []}
1
Where 1 is my maximum dictionary depth. I was expecting the depth to be two, but there appears to be only 1 layer to the graph of 'POT'
How can I find the maximum value set from the set of keys in a dictionary?
import pprint
def dict_depth(d, depth=0):
if not isinstance(d, dict) or not d:
return depth
print max(dict_depth(v, depth+1) for k, v in d.iteritems())
def main():
for keyCheck in wordDict:
for keyCompare in wordDict:
if keyCheck in keyCompare:
if keyCheck != keyCompare:
wordDict[keyCheck].append(keyCompare)
if __name__ == "__main__":
#load the words into a dictionary
wordDict = dict((x.strip(), []) for x in open("testwordlist.txt"))
main()
pprint.pprint (wordDict)
dict_depth(wordDict)
testwordlist.txt:
POT
SUPERPOT
HIPPOPOTIMUS
DOG
The "depth" of a dictionary will naturally be 1 plus the maximum depth of its entries. You've defined the depth of a non-dictionary to be zero. Since your top-level dictionary doesn't contain any dictionaries of its own, the depth of your dictionary is clearly 1. Your function reports that value correctly.
However, your function isn't written expecting the data format you're providing it. We can easily come up with inputs where the depth of substring chains is more than just one. For example:
DOG
DOGMA
DOGMATIC
DOGHOUSE
POT
Output of your current script:
{'DOG': ['DOGMATIC', 'DOGMA', 'DOGHOUSE'],
'DOGHOUSE': [],
'DOGMA': ['DOGMATIC'],
'DOGMATIC': [],
'POT': []}
1
I think you want to get 2 for that input because the longest substring chain is DOG → DOGMA → DOGMATIC, which contains two hops.
To get the depth of a dictionary as you've structured it, you want to calculate the chain length for each word. That's 1 plus the maximum chain length of each of its substrings, which gives us the following two functions:
def word_chain_length(d, w):
if len(d[w]) == 0:
return 0
return 1 + max(word_chain_length(d, ww) for ww in d[w])
def dict_depth(d):
print(max(word_chain_length(d, w) for w in d))
The word_chain_length function given here isn't particularly efficient. It may end up calculating the lengths of the same chain multiple times if a string is a substring of many words. Dynamic programming is a simple way to mitigate that, which I'll leave as an exercise.
Sorry my examples wont be in python because my python is rusty but you should get the idea.
Lets say this is a binary tree:
(written in c++)
int depth(TreeNode* root){
if(!root) return 0;
return 1+max(depth(root->left), depth(root->right));
}
Simple. Now lets expand this too more then just a left and right.
(golang code)
func depthfunc(Dic dic) (int){
if dic == nil {
return 0
}
level := make([]int,0)
for key, anotherDic := range dic{
depth := 1
if ok := anotherDic.(Dic); ok { // check if it does down further
depth = 1 + depthfunc(anotherDic)
}
level = append(level, depth)
}
//find max
max := 0
for _, value := range level{
if value > max {
max = value
}
}
return max
}
The idea is that you just go down each dictionary until there is no more dictionaries to go down adding 1 to each level you traverse.
I have a code to update a dictionary like this :
c = { }
for i in ID :
d = {i : V[i]}
c.update(d)
Both ID and V are sequence data with a complex and huge items, where ID is a list and V is a dictionary.
Is there any ways in python to do that logic without using loop processes like "for"?
The use of loop processes take a lot of iteration impacted on run time.
No, you can't avoid a loop but you can try these alternatives:
c = { }
for i in ID :
c[i] = V[i]
or
c = dict([(i, V[i]) for i in ID])
or
c = {i: V[i] for i in ID}
the short way of your code is:
c.update({i:V[i] for i in ID})
also you could use map, but it will iterate over
c.update(dict(map(lambda i:(i,V[i]),ID)))
Its all O(n) and you could just move it into C part rather than Python by using above notations!
I have a list and I want to binary_search a key(number).
My code is below but I don't have a clue what to do where the bold text on code is:
(What to do with this? Is an other function? int imid = midpoint(imin, imax))
List = []
x = 1
#Import 20 numbers to list
for i in range (0,20):
List.append (i)
print (List)
key = input("\nGive me a number for key: ")
def midpoint(imin, imax):
return point((imin+imax)/2)
def binary_search(List,key,imin,imax,point):
while (imax >= imin):
int imid = midpoint(imin, imax)
if(List[imid] == key):
return imid;
elif (List[imid] < key):
imin = imid + 1;
else:
imax = imid - 1;
return KEY_NOT_FOUND;
print (binary_search(key))
midpoint(imin, imax)
binary_search(List,key,imin,imax,point)
It doesn't seem to be doing anything for you; remove the call to midpoint, and point, and just have
def binary_search(List,key,imin,imax,point):
while (imax >= imin):
imid = (imin + imax) / 2
(However, there are some things wrong with your code, and it won't work with just that change;
You create a list called List then try to append to an uninitialized variable called myList
You 'import 20 random' numbers, but range() is not random, it's a simple sequence 1, 2, 3, 4...
range already returns a list, no need to count through it and copy it, just use it
You call binary_search with an empty List, a key, and three uninitialized variables
binary_search assumes the list is sorted, which it is, but if the comment about 'random numbers' was correct, it wouldn't be.
)