I have run into a very frustrating problem in Python. I am trying to make a sorting algorithm that works like so:
I read one variable from a list
I check how many variables have a lower value than that variable and assign that to a place variable
The current variable is put in its place
continue to the next variable and repeat
The problem is that the dummy variable automatically resets to zero after being incremented. I can't do step by step program running, so figuring out what's wrong is very difficult.
I have very little experience with python, so any help is greatly appreciated.
# sorting algorithm
theList = [9, 7, 8, 5, 6, 3, 4, 1, 2, -1]
def order(n):
a = 0
m = n
print(n)
print(m)
while a < len(n):
b = 0
c = 0 #this is where the problem is
while b < len(n):
if n[b] < n[a]:
c += 1 # after this if statement isn't true, c reverts to zero
print(c)
b += 1
#I think I should be able to put m[c] = n[a], but this doesn't work
a += 1
print(n)
print(m)
order(theList)
m = n
Does not create a new list. It just maps the name m to the same list that n points to. So when you do m[c] = n[a] the original list also changes - hence the unexpected behaviour.
Try:
def order(n):
a = 0
m = n[:] # create copy
print(n)
print(m)
while a < len(n):
b = 0
c = 0
while b < len(n):
if n[b] < n[a]:
c += 1
print(c)
b += 1
m[c] = n[a] # assign in output
a += 1
print(n)
print(m)
This does create a copy & seems to solve the issue:
...
[9, 7, 8, 5, 6, 3, 4, 1, 2, -1]
[-1, 1, 2, 3, 4, 5, 6, 7, 8, 9]
PS: sorting should not require a copy of the list to be made. There are better algorithms that can modify the list in-place.
Related
I am trying to create a program that adds to a specific variable when the list of integers change from positive to negative to neutral etc, but I keep getting the output of 8 instead of 7 but cannot find the bug. Please see my code below
def changing_direction(elements: list[int]) -> int:
#to check whether true or false with ones and zeros
x = 0
#to store last number to check with new number
a = 0
#to subtract last number from new number
b = 0
d = 0
e = 0
for i in elements:
b = a - i
if b > 0:
x = 1
elif b < 0:
x = 0
elif b != 0:
a = i
e = x
break
if x != e:
d += 1
a = i
e = x
return d
print("Example:")
print(changing_direction([6, 6, 6, 4, 1, 2, 5, 9, 7, 8, 5, 9, 4, 2, 6]))
You would need to keep track of the last direction - you can easily ignore all directions if they do not differ - no need to keep x.
You also need to keep track of the amount of changes.
This could be done like this:
def changing_direction(elems: list[int]) -> int:
# can not compare with 0 or 1 elem => 0 changes
if len(elems) < 2:
return 0
changes = 0
# helper, returns UP or DOWN or umplicit None based on b-a
def ud(a,b):
if b-a > 0: return "UP"
if b-a < 0: return "DOWN"
# current start direction
direction = None
for idx, e in enumerate(elems):
try:
# save old direction, initially None
ld = direction
# get new direction, maybe None
direction = ud(e,elems[idx+1])
print(direction) # --> comment for less output
# if both are not None and different we have a change in direction
# if either is None: same values this and last time round
#
if direction is not None and ld is not None and ld != direction:
changes += 1
if direction is None and ld is not None:
direction = ld # restore last direction for next time round
except IndexError:
pass # end of list reached
return changes
print("Example:")
print(changing_direction([6, 6, 6, 4, 1, 2, 5, 9, 7, 8, 5, 9, 4, 2, 6]))
to get:
Example:
None
None
DOWN
DOWN
UP
UP
UP
DOWN
UP
DOWN
UP
DOWN
DOWN
UP
7
Using proper variable names hopefully makes is easy to understand. If you store the "UP","DOWN" in a list you can also use that to count your changes by simply iterating over it.
For a more compact way to count this, look into list comprehensions.
You could simplify your function significantly by using zip() and list comprehension, which makes it return the correct value where the first change is not counted.
def changing_direction(elements: list[int]) -> int:
diffs = (i-j for i,j in zip(elements[:-1], elements[1:]) if i-j!=0)
return sum(i*j < 0 for i,j in zip(diffs[:-1], diffs[1:]))
zip(somelist[:-1], somelist[1:]) basically returns tuples containing consecutive elements as a generator.
We remove all the 0 elements because they cause problems in the following logic.
The main logic here is that 2 consecutive differences when multiplied together will be negative if the direction changes
sum here works to count things because True counts as a 1, and False counts as a 0
finally, you could have this as a 1 line lambda if you knew that lists did not have 2 consecutive items as the same value.
changing_direction = lambda seq: sum((i-j)*(j-k)<0 for i,j,k in zip(seq, seq[1:], seq[2:]))
such that
changing_direction([6, 6, 6, 4, 1, 2, 5, 9, 7, 8, 5, 9, 4, 2, 6])
retults in 7
G'day. I am new to coding and python.
My goal is to try to create a code where if the element in y reaches the next 0, all the 0 to n (before the next zero) will become n. A sample output should look like this after executing the code below:
y = [0,1,2,3,4,5,6,7,8,0,1,0,1,2,3,4,5,6,7]
# I am interating over two inputs. y_1 = y[1:] and append 0 at the end.
y_1 = [1,2,3,4,5,6,7,8,0,1,0,1,2,3,4,5,6,7,0]
expected output:
x = [8, 8, 8, 8, 8, 8, 8, 8, 8, 1, 1, 7, 7, 7, 7, 7, 7, 7, 7]
The problem I'm facing I believe comes from the while loop not looping over after [0,1,2,3,4,5,6,7,8] is deleted from the list as specified in the code below (which logically to me should loop over?) :
y = [0,1,2,3,4,5,6,7,8,0,1,0,1,2,3,4,5,6,7]
y_1 = [1,2,3,4,5,6,7,8,0,1,0,1,2,3,4,5,6,7,0]
x = []
while len(y):
for i, j in zip(y, y_1):
if i > j:
z = i
for k in range(z+1):
x.append(y[i])
del y[0:z+1]
del y_1[0:z+1]
elif i == j:
z = 0
x.append(z)
del y[z]
del y_1[z]
Any suggestion would be greatly appreciated :)
I don't know why you use del and while because you should get expected result doing
y = [0,1,2,3,4,5,6,7,8,0,1,0,1,2,3,4,5,6,7]
y_1 = y[1:] + [0]
x = []
for i, j in zip(y, y_1):
if i > j:
z = i
for k in range(z+1):
x.append(y[i])
elif i == j:
z = 0
x.append(z)
print(x)
In Python you shouldn't delete element from list which you use as for-loop because when it delete element then it moves other elements in list used as for-loop and it can give unexpected results.
If you really want to run it in some while len(y) then you should rather create new list with elements which you want to keep. Or you should duplicate list - y_duplicated = y.copy() - and delete in duplicated list and after for-loop replace original list y = y_duplicated
I need to iterate sequentially until I find or maximize.
For example:
ds = [1,2,3,4,5,6,7,8,9]
tmp = 3 # start (variable)
max = 5 # maximize (variable)
target = 8
so output: [4,5,6,7,8]
Sorry, my english is not good.
As a very simple approach you could index over the concatenation with the same list.
However, from memory point of view certainly not the best solution.
# ds = [1,2,3,4,5,6,7,8,9]
start = 4
length = 7
res = (ds + ds)[start:start+length]
# [5, 6, 7, 8, 9, 1, 2]
There is a built-in way to do this.
new_data = i[starting_index : ending_index]
You can leave a number blank if you want to get the rest of the list. Like:
>>>i = [0,8,9,4]
>>>i[1:]
[8,9,4]
see this solution i used a for loop to reach your target
ds = [1,2,3,4,5,6,7,8,9]
tmp = 3 # start (variable)
max = 5 # maximize (variable)
target=8
i=0 # itiration to loop on the list
for x in ds:
if ds[i]<tmp: #till now we didnt reach start point
i=i+1
else:
print(ds[i])
i=i+1
if i == target: #since the target has been reached
break
Try:
>>> ds
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> (ds * ((5+6)//len(ds) + 1))[5:5+6]
[6, 7, 8, 9, 1, 2]
Now - 5 is your starting position 5+6 is your end position. You want to iterate over whole data set, as many times to contain end position, so:
((5+6)//len(ds) + 1)
In case if your starting position would be in second, or later repetition (so in your case if it would > 8. You can move it back by subtracting:
(startPosition//len(ds)) * len(ds)
from both start position, and end position.
here is my code
I am wondering why i cannot put a 'for loop' into a function
>>> a=[5,3,5,6,8,9,0,1,3]
>>> def classification(input):
scoreget=0
for i in range(0,8):
if input[i]>2:
scoreget+=1
else:
scoreget+=0
return scoreget
>>> result=classification(a)
>>> print result
The result should be [1,1,1,1,1,1,0,0,1], but it showed only one value '1',not a set.
The way functions work in Python is that first the entire for loop is done and next the output of the function is returned. In this case that means that only the last output is returned. Also your range doesn't cover all the input parameters, which can be resolved using len. Below is an example of your code which would work:
a = [5, 3, 5, 6, 8, 9, 0, 1, 3]
def classification(inputs):
scoreget = 0
score = []
for i in range(len(inputs)):
if inputs[i] > 2:
scoreget = 1
else:
scoreget = 0
score.append(scoreget)
return score
result = classification(a)
print result
I have a for loop that gives me the following output.
0.53125
0.4375
0.546875
0.578125
0.75
0.734375
0.640625
0.53125
0.515625
0.828125
0.5
0.484375
0.59375
0.59375
0.734375
0.71875
0.609375
0.484375
.
.
.
How do I find the mean of the first 9 values, the next 9 values and so on and store them into a list like [0.58,0.20,...]? I have tried a lot of things but the values seem to be incorrect. What is the correct way of doing this?
What I did:
matchedRatioList = []
matchedRatio = 0
i = 0
for feature in range(90):
featureToCompare = featuresList[feature]
number = labelsList[feature]
match = difflib.SequenceMatcher(None,featureToCompare,imagePixList)
matchingRatio = match.ratio()
print(matchingRatio)
matchedRatio += matchingRatio
if i == 8:
matchedRatioList.append(matchedRatio / 9)
i = 0
matchedRatio = 0
i += 1
Once you have the list of numbers you can calculate the average of each group of 9 numbers using list comprehensions:
from statistics import mean
numbers = [0.53125, 0.4375, 0.546875, 0.578125, 0.75, 0.734375, 0.640625,
0.53125, 0.515625, 0.828125, 0.5, 0.484375, 0.59375, 0.59375,
0.734375, 0.71875, 0.609375, 0.484375]
group_len = 9
matched_ratios = [mean(group) for group in [numbers[i:i+group_len]
for i in range(0, len(numbers), group_len)]]
print(matched_ratios)
# [0.5850694444444444, 0.6163194444444444]
Your solution is close. Start with i = 1 and check for i == 9
matchedRatioList = []
matchedRatio = 0
i = 1 # change here
for feature in range(90):
...
matchedRatio += matchingRatio
if i == 9: # change here
matchedRatioList.append(matchedRatio / 9)
i = 0
matchedRatio = 0
i += 1
I do not know what you have tried so far, but I can present you with one solution to the problem.
Save all values in your for-loop to a buffer array. Use an if-statement with iterator % 9 == 0 inside your for-loop, which will make some portion of code execute only every 9 values.
Inside the if-statement you can write the mean value of your buffer array to a different output array. Reset your buffer array inside this if-statement as well, then this process is repeated and should behave in the way you want.
Try this
r = []
for b in a:
c += b
if i == 8:
c = c/9
r.append(c)
c = 0
i = 0
i += 1
since nobody used reduce so far :)
import functools
l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
m = []
for i in range(9,len(l), 9):
m.append(functools.reduce(lambda x, y: x + y, l[i-9:i])/9)
print(m)
Using mean function from the statistics module of Python.
import statistics
# Sample Values list I created.
values_list = list()
for i in range(1,82):
values_list.append(i)
mean_list = list()
for i in range(0, len(values_list), 9):
mean_list.append(statistics.mean(values_list[i:i+9]))
for i in mean_list:
print(i)
This is the simplest way in which you can do it.
https://docs.python.org/3/library/statistics.html#statistics.mean
One-line solution given loop output in numbers:
[float(sum(a))/len(a) for a in zip(*[iter(numbers)]*9)]
Putting ideas from the other answers together, this could be the whole program:
from statistics import mean
matching_ratios = (difflib.SequenceMatcher(None, feature, imagePixList).ratio()
for feature in featuresList[:90])
matchedRatioList = [mean(group) for group in zip(*[matching_ratios] * 9)]