Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I have an assignment where I am to count the occurrences of consecutive 1:s in a sequence. This is where I'm at. Why doesn't this work?
def count11(seq):
x = 0
for i in seq:
if i == 1:
if seq[i+1] == 1:
x += 1
return x
print(count11([0, 0, 1, 1, 1, 0]))
Edit: The function is supposed to count the number of pairs of ones, so the given sequence should output 2.
You can also make a one-liner:
import re
import math
def count(seq):
return math.ceil(len(max(re.sub(r"[^1]"," ","".join(map(str, seq))).split(), key=len))/2)
print (count([0, 0, 1, 1, 1, 0]))
This returns the max number of pairs (longest repeat / 2 round up), two (overlapping) pairs in your example.
Code Review and fix
First let's review your code:
for i in seq
The for loop will get you each element from the sequence. So this will be values of 0s and 1s.
Inside the loop, you are checking
if seq[i+1] == 1:
Since the values of i can be only 0 or 1, you are checking through the loop for values of seq[1] or seq[2] depending on the value of i in the list seq. Instead, you should iterate through the list for the length of seq - 1 times (since python list index starts from 0).
To do that, you can set the counter to 0 and for every iteration inside the for loop, increment the counter by 1 and use that to check seq. Python makes it easy by having enumerate(seq). This will give you a tuple (counter, value). That way you have direct access to the counter and can use that to check the counter + 1 value as well. Or you can iterate through the loop using range (0 to len of seq - 1).
Your modified code will be as follows:
def count11(seq):
x = 0
for i in range (len(seq)-1):
if seq[i] == seq[i+1] == 1: #check if ith and i+1th position are both equal to 1
x += 1
return x
For a value of [0, 0, 1, 1, 1, 0], the result will be 2
Alternate solutions:
There are three types of consecutive checks we can do. I am going to give you code for all 3 types.
Type 1: If the value is [1, 1, 1, 0, 1, 1], there are two sequence of 1s in this list. So the result can be 2.
Type 2: An alternate way to look at this is to find any two elements and if they are both 1s, then count it as sequence. If that's the case, the result will be 3 (1, 1 for first and second, then 1, 1 for second and third, then 1, 1 for last two elements).
Type 3: Another check you can do is to find the highest sequence of 1s in a list. In this case, the highest will be 3.
In the below code,
consec_a function will result in 3 (check if the next element is also a 1). This solution is similar to what you have. I have made it a list comprehension and a single line.
consec_b function will result in 2 (check if there is a series of uninterrupted 1s)
consec_c function will check for 3 (find the max number of uninterrupted 1s)
def consec_a(sequ):
return sum(sequ[i] == sequ[i+1] == 1 for i in range(len(sequ)-1))
def consec_b(sequ):
seq_flag = False
seq_count = 0
for i in range (len(sequ)-1):
if sequ[i] == sequ[i+1] == 1:
if not seq_flag: seq_count += 1
seq_flag = True
else: seq_flag = False
return seq_count
def consec_c(sequ):
seq_flag = False
seq_count = 1
max_count = 0
for i in range (len(sequ)-1):
if sequ[i] == sequ[i+1] == 1:
seq_count += 1
if max_count < seq_count: max_count = seq_count
seq_flag = True
else:
seq_flag = False
seq_count = 1
return max_count
print ('Results of consec_a function :')
print('[0, 0, 1, 1, 1, 0]', consec_a([0, 0, 1, 1, 1, 0]))
print('[0, 1, 1, 0, 1, 1]', consec_a([0, 1, 1, 0, 1, 1]))
print('[1, 1, 1, 0, 1, 1]', consec_a([1, 1, 1, 0, 1, 1]))
print('[1, 1, 1, 1, 1, 1]', consec_a([1, 1, 1, 1, 1, 1]))
print('[0, 0, 0, 0, 0, 0]', consec_a([0, 0, 0, 0, 0, 0]))
print ('\nResults of consec_b function :')
print('[0, 0, 1, 1, 1, 0]', consec_b([0, 0, 1, 1, 1, 0]))
print('[0, 1, 1, 0, 1, 1]', consec_b([0, 1, 1, 0, 1, 1]))
print('[1, 1, 1, 0, 1, 1]', consec_b([1, 1, 1, 0, 1, 1]))
print('[1, 1, 1, 1, 1, 1]', consec_b([1, 1, 1, 1, 1, 1]))
print('[0, 0, 0, 0, 0, 0]', consec_b([0, 0, 0, 0, 0, 0]))
print ('\nResults of consec_c function :')
print('[0, 0, 1, 1, 1, 0]', consec_c([0, 0, 1, 1, 1, 0]))
print('[0, 1, 1, 0, 1, 1]', consec_c([0, 1, 1, 0, 1, 1]))
print('[1, 1, 1, 0, 1, 1]', consec_c([1, 1, 1, 0, 1, 1]))
print('[1, 1, 1, 1, 1, 1]', consec_c([1, 1, 1, 1, 1, 1]))
print('[0, 0, 0, 0, 0, 0]', consec_c([0, 0, 0, 0, 0, 0]))
The output of this will be:
Results of consec_a function :
[0, 0, 1, 1, 1, 0] 2
[0, 1, 1, 0, 1, 1] 2
[1, 1, 1, 0, 1, 1] 3
[1, 1, 1, 1, 1, 1] 5
[0, 0, 0, 0, 0, 0] 0
Results of consec_b function :
[0, 0, 1, 1, 1, 0] 1
[0, 1, 1, 0, 1, 1] 2
[1, 1, 1, 0, 1, 1] 2
[1, 1, 1, 1, 1, 1] 1
[0, 0, 0, 0, 0, 0] 0
Results of consec_c function :
[0, 0, 1, 1, 1, 0] 3
[0, 1, 1, 0, 1, 1] 2
[1, 1, 1, 0, 1, 1] 3
[1, 1, 1, 1, 1, 1] 6
[0, 0, 0, 0, 0, 0] 0
Hopefully the code is easy to understand. If you need clarification, let me know.
I am using chaining to check for 1s.
if sequ[i] == sequ[i+1] == 1
This checks if all the values are equal to 1 and if yes, then the equation is set to True
sum(sequ[i] == sequ[i+1] == 1 .....)
This sums all the True values. As you know True = 1 and False = 0.
You try to use i as your index, which is the current item in the sequence, and not its index. At that point, i is always 1, because you checked it before. A way to solve it would be using emumerate, which gives you a tuple with the current item itself and its index.
for idx, item in enumerate(seq):
# idx is the index, item is 1 or 0
the i in your code is the item in seq, not the index of seq. you can get the first consecutive 1s through the following codes:
def count11(seq):
count = 0
for item in seq:
if not item and count == 0:
continue
elif item == 1:
count += 1
else:
break
return count
if you want to get the max consecutive 1s:
def count11(seq):
if not seq:
return 0
count = 0
max_count = 0
for item in seq:
if item == 1:
count += 1
max_count = max(max_count, count)
else:
count = 0
return max_count
You can find a similar question and variations to it for practice LeetCode - Max Consecutive Ones
Below was my solution for it
Intuition of the solution -
Maintain c(counter) to track the current run of 1s. Update the max_run after increment of cnt.
Reset c(counter) to 0 when we encounter 0 in the array.
def findMaxConsecutiveOnes(nums):
n = len(nums)
if n == 1 and nums[0] == 1:
return 1
res = 0
c = 0
for i in range(n):
if nums[i] == 1:
c += 1
res = max(c,res)
else:
c = 0
return res
>>> findMaxConsecutiveOnes([0, 0, 1, 1, 1, 0])
3
Related
I have a data list like the following data = [1, 0, 0, 0, 1, 1, 1, 0, 2, 3, 1, 0, 0, 1, 1, 1, 0] and I want to add up the elements of the list to be like this:
[1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 0, 3, 0], where the previous element is the value 0 and the last element other than 0 is the result of the value of the previous number of elements.
I've tried with the following code, if I do the trace, it looks like it can be done, but when I run it it doesn't show results but it's still in the loop that doesn't stop.
I tried it with :
data = [1, 0, 0, 0, 1, 1, 1, 0]
k = len(data)-1
while True:
print(k)
if(data[k-1] == 0):
continue
elif(data[k] == 0):
print("h")
continue
elif(data[k-1] != 0):
data[k] = data[k] + data[k-1]
data[k-1] = 0
k = k-1
if(k == 0):
break
print(data)
Iterate through the list and just add every time a non - zero number
and append a zero to the list.
when there is a 0 appearing just append the sum and make sum 0.
if the last element is 0 add zero to the last number or the
respective last number.
Just remove the first zero and return the list.
.
data = [1, 0, 0, 0, 1, 1, 1, 0, 2, 3, 1, 0, 0, 1, 1, 1, 0]
def calc(data):
sum = 0
new = []
for i in range(len(data)):
if data[i] == 0:
new.append(sum)
if i == len(data) - 1:
new.append(0)
sum = 0
else:
sum = sum = sum + data[i]
new.append(0)
if i == len(data) - 1:
new.append(sum)
if new[0] == 0:
del new[0]
return new
Here is a very simple implementation. I think it is quite self-explanatory. You iterate over each item n in the list, if n is zero, you have two options a) if there is a previous sum x, append x and then n b) if there is no sum, just append 0.
If n is different from zero, sum it to x.
data = [1, 0, 0, 0, 1, 1, 1, 0, 2, 3, 1, 0, 0, 1, 1, 1, 0]
x = 0
r = []
for n in data:
if n == 0:
if x:
r.append(x)
x = 0
r.append(n)
else:
x += n
print(r)
[1, 0, 0, 0, 3, 0, 6, 0, 0, 3, 0]
Iterate through the list and if current and next element are not 0 then add to a temp variable and put current element as 0, when the next element is zero put the value in the current element. Since, code checks for the next element with the current element, Iterate through 2nd last element and check for the last separately.
def arrange_list(arr):
value = 0
for x in range(len(arr)-1):
if arr[x] != 0:
value += arr[x]
else:
value = 0
if arr[x+1] != 0:
arr[x] = 0
else:
arr[x] = value
value = 0
if value !=0:
arr[-1] = value + arr[-1]
return arr
As Mentioned in the Comments you get to an infinite loop because of all the continues. You need to make sure that the line k=k-1 happens to avoid infinite loop.
Second why do while True and then if k==0: break change it to while k>=0.
Anyway your code won't work because it will have a problem with elements that follow a zero.
This code will work:
ans = []
tmp = 0
data = [1, 0, 0, 0, 1, 1, 1, 0]
for curr in data:
if curr != 0:
tmp += curr
elif tmp == 0:
ans.append(tmp)
else:
ans.append(tmp)
ans.append(0)
tmp = 0
print(ans)
You just need to start the value of k from 1 and set elif(data[k] != 0):. However, it will modify your original list.
data=[1, 0, 0, 0, 1, 1, 1, 0, 2, 3, 1, 0, 0, 1, 1, 1, 0]
k = 1
while True:
if(data[k-1] == 0):
pass
elif(data[k] == 0):
pass
elif(data[k] != 0):
data[k] = data[k] + data[k-1]
print(data[k])
data[k-1] = 0
k = k+1
if(k == len(data)):
break
print(data)
Output
3
5
6
2
3
[1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 0, 3, 0]
Here your code is running to infinite loop as you are using continue
statement which will again start the loop from beginning.
As in your case data[k] is zero so the first elif statement is always true
and the continue statement is executing.
Because of the above reason the code k=k-1 line is always unreachable and k value is always 7 in your case. So the while loop is running infinitely.
Below is a suggested code sample which satisfies your use case.
data = [1, 0, 0, 0, 1, 1, 1, 0, 2, 3, 1, 0, 0, 1, 1, 1, 0]
k = len(data)-1
for i in range(0,k):
if(data[i]==0):
continue
if(data[i]!=0 and data[i+1]!=0):
data[i+1]=data[i]+data[i+1]
data[i]=0
print(data)
Why not do it like this:
def convert(A):
B = [0] * len(A)
partial_sum = 0
for i in range(len(A) - 1):
partial_sum += A[i]
if A[i + 1] == 0:
B[i] = partial_sum
partial_sum = 0
if A[-1] != 0:
B[-1] = partial_sum + A[-1]
return B
As opposed to the previous answer, this actually preserves the length of the original array.
You could define a general reusable method which comes in hand in some cases.
Here it is, it returns a generator:
def slice_when(predicate, iterable):
i, x, size = 0, 0, len(iterable)
while i < size-1:
if predicate(iterable[i], iterable[i+1]):
yield iterable[x:i+1]
x = i + 1
i += 1
yield iterable[x:size]
Example of usage
Once you have in place this method, you can use it in this way:
data = [1, 0, 0, 0, 1, 1, 1, 0, 2, 3, 1, 0, 0, 1, 1, 1, 0]
test_method = slice_when(lambda _, y: y==0, data)
list(test_method)
#=> [[1], [0], [0], [0, 1, 1, 1], [0, 2, 3, 1], [0], [0, 1, 1, 1], [0]]
Your case
This is how to apply it for solving your point:
res = []
for e in slice_when(lambda _, y: y==0, data):
res += [0]*(len(e)-1) + [sum(e)]
res
#=> [1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 0, 3, 0]
I have a 1D numpy array of 1's and 0's. I need to change it to an array according to these conditions.
If the number of 0's between two 1's is less than 3, all of those 0's should be set to 1.
In the resulting array, if the number of consecutive 1's are less than 4, all of those 1's should be set to 0.
i.e if my array is
[0,1,1,1,0,0,0,1,1,0,0,1,1,0,0,0,0,1,0]
it should be changed to
[0,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,0,1,0]
and then to
[0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0]
I have tried using moving average to no avail. How do I write a general function, preferably with n instead of 3 and m instead of 4?
If you use core Python?
l = [0,1,1,1,0,0,0,1,1,0,0,1,1,0,0,0,0,1,0]
def split(l):
res = []
subres = [l[0]]
for i in range(len(l) - 1):
if l[i] == l[i + 1]:
subres.append(l[i + 1])
else:
res.append(subres)
subres = [l[i + 1]]
res.append(subres)
return(res)
def setall(l, val):
for i in range(len(l)):
l[i] = val
return(l)
def recode(l, changeval, replaceval, lenlimit):
for i in range(len(l) - 1):
el = l[i + 1]
if (el[0] == changeval) & (len(el) < lenlimit) & (i < (len(l) - 2)):
el = setall(el, replaceval)
l[i + 1] = el
return(l)
def flatten(l):
res = []
for el in l:
res.extend(el)
return(res)
# starting list
print(l)
# step 1
want1 = split(l)
want1 = flatten(recode(want1, 0, 1, 3))
print(want1)
# step 2
want2 = split(want1)
want2 = flatten(recode(want2, 1, 0, 4))
print(want2)
#[0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0]
#[0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0]
#[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]
You are given an integer array with N elements: d[0], d[1], ... d[N - 1].
You can perform AT MOST one move on the array: choose any two integers [L, R], and flip all the elements between (and including) the L-th and R-th bits. L and R represent the left-most and right-most index of the bits marking the boundaries of the segment which you have decided to flip.
What is the maximum number of 1-bits (indicated by S) which you can obtain in the final bit-string?
'Flipping' a bit means, that a 0 is transformed to a 1 and a 1 is transformed to a 0 (0->1,1->0).
Input Format: An integer N, next line contains the N bits, separated by spaces: d[0] d[1] ... d[N - 1]
Output: S
Constraints:
1 <= N <= 100000,
d[i] can only be 0 or 1 ,
0 <= L <= R < n ,
Sample Input:
8
1 0 0 1 0 0 1 0
Sample Output: 6
Explanation:
We can get a maximum of 6 ones in the given binary array by performing either of the following operations:
Flip [1, 5] ==> 1 1 1 0 1 1 1 0
Cleaned up and made Pythonic
arr1 = [1, 0, 0, 1, 0, 0, 1, 0]
arr2 = [1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1]
arr3 = [0,0,0,1,1,0,1,0,1,1,0,0,1,1,1]
def maximum_ones(arr):
"""
Returns max possible number of ones after flipping a span of bit array
"""
total_one = 0
net = 0
maximum = 0
for bit in arr:
if bit:
total_one += 1
net -= 1
else:
net += 1
maximum = max(maximum, net)
if net < 0:
net = 0
return total_one + maximum
print(maximum_ones(arr1))
print(maximum_ones(arr2))
print(maximum_ones(arr3))
Output:
6
14
11
If we want the L and R indices
Not so sure about this one. It can probably be made cleaner.
arr1 = [1, 0, 0, 1, 0, 0, 1, 0]
arr2_0 = [1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1]
arr2_1 = [1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1]
arr2_2 = [1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1]
arr3 = [0,0,0,1,1,0,1,0,1,1,0,0,1,1,1]
def maximum_ones(arr):
"""
Returns max possible number of ones after flipping a span of bit array
and the (L,R) indices (inclusive) of such a flip
"""
total_one = 0
net = 0
maximum = 0
L = R = 0
started_flipping = False
for i, bit in enumerate(arr):
if bit:
total_one += 1
net -= 1
else:
net += 1
if not started_flipping:
started_flipping = True
L = i
if net > maximum:
maximum = net
R = i
if net < 0:
net = 0
if i < R:
L = i
return (total_one + maximum, (L,R))
print(maximum_ones(arr1))
print(maximum_ones(arr2_0))
print(maximum_ones(arr2_1))
print(maximum_ones(arr2_2))
print(maximum_ones(arr3))
Output:
(6, (1, 5))
(14, (1, 16))
(14, (2, 16))
(14, (3, 16))
(11, (0, 2))
First Iteration
Here is what I had originally, if you want to see the evolution of the thought processes. Here, I was essentially transliterating what I came up with on paper.
Essentially, we traverse the array and start flipping bits (ok, not really), keeping track of cumulative flipped zeros and cumulative flipped ones in two separate arrays along with the total flipped ones in an integer counter. If the difference between flipped ones and zeroes at a given index - the "net" - drops below zero, we 'reset' the cumulative counts back at zero at that index (but nothing else). Along the way, we also keep track of the maximum net we've achieved and the index at which that occurs. Thus, the total is simply the total 1's we've seen, plus the net at the maximum index.
arr = [1, 0, 0, 1, 0, 0, 1, 0]
total_one = 0
one_flip = [0 for _ in range(len(arr))]
zero_flip = [0 for _ in range(len(arr))]
# deal with first element of array
if arr[0]:
total_one += 1
else:
zero_flip[0] = 1
maximum = dict(index=0,value=0) #index, value
i = 1
# now deal with the rest
while i < len(arr):
# if element is 1 we definitely increment total_one, else, we definitely flip
if arr[i]:
total_one += 1
one_flip[i] = one_flip[i-1] + 1
zero_flip[i] = zero_flip[i-1]
else:
zero_flip[i] = zero_flip[i-1] + 1
one_flip[i] = one_flip[i-1]
net = zero_flip[i] - one_flip[i]
if net > 0:
if maximum['value'] < net:
maximum['value'] = net
maximum['index'] = i
else: # net == 0, we restart counting our "net"
one_flip[i] = 0
zero_flip[i] = 0
i += 1
maximum_flipped = total_one - one_flip[maximum['index']] + zero_flip[maximum['index']]
Results:
print(total_one, -one_flip[maximum['index']], zero_flip[maximum['index']] )
print(maximum_flipped)
print('________________________________________________')
print(zero_flip, arr, one_flip, sep='\n')
print('maximum index', maximum['index'])
Output:
3 -1 4
6
________________________________________________
[0, 1, 2, 2, 3, 4, 4, 5]
[1, 0, 0, 1, 0, 0, 1, 0]
[0, 0, 0, 1, 1, 1, 2, 2]
maximum index 5
if arr = [1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1]
6 -4 12
14
________________________________________________
[0, 1, 2, 3, 3, 4, 5, 5, 6, 6, 7, 8, 9, 10, 10, 11, 12, 12]
[1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1]
[0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 5]
maximum index 16
Finally, if arr = [0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1]
8 0 3
11
________________________________________________
[1, 2, 3, 3, 3, 4, 4, 5, 5, 0, 1, 2, 2, 0, 0]
[0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1]
[0, 0, 0, 1, 2, 2, 3, 3, 4, 0, 0, 0, 1, 0, 0]
maximum index 2
Great, now tear it apart, people!
Traverse the whole array. Keep a count in the following way:
Do +1 for every 0 bit encountered.
Do -1 for every 1.
If this count reaches -ve at any stage, reset it to 0. Keep track of max value of this count. Add this max_count to number of 1's in input array. This will be your answer.
Code:
arr = [1, 0, 0, 1, 0, 0, 1, 0]
# I'm taking your sample case. Take the input the way you want
count,count_max,ones = 0,0,0
for i in arr:
if i == 1:
ones += 1
count -= 1
if i == 0:
count += 1
if count_max < count:
count_max = count
if count < 0:
count = 0
print (ones + count_max)
Small and simple :)
Seemingly straightforward problem: I want to create an array that gives the count since the last occurence of a given condition. In this condition, let the condition be that a > 0:
in: [0, 0, 5, 0, 0, 2, 1, 0, 0]
out: [0, 0, 0, 1, 2, 0, 0, 1, 2]
I assume step one would be something like np.cumsum(a > 0), but not sure where to go from there.
Edit: Should clarify that I want to do this without iteration.
Numpy one-liner:
x = numpy.array([0, 0, 5, 0, 0, 2, 1, 0, 0])
result = numpy.arange(len(x)) - numpy.maximum.accumulate(numpy.arange(len(x)) * (x > 0))
Gives
[0, 1, 0, 1, 2, 0, 0, 1, 2]
If you want to have zeros in the beginning, turn it to zero explicitly:
result[:numpy.nonzero(x)[0][0]] = 0
Split the array based on the condition and use the lengths of the remaining pieces and the condition state of the first and last element in the array.
A pure python solution:
result = []
delta = 0
for val in [0, 0, 5, 0, 0, 2, 1, 0, 0]:
delta += 1
if val > 0:
delta = 0
result.append(delta)
I am having a dict(containing lists) and a list, which I want to compare:
The first thing, I want to find out is whether each value-list (e.g. for issue1, the value-list is [1, 1, 0, 0, 0, 1, 1, 1]) in ref has the same length as the list abf.
Then comes the tricky part: If they have the same length, I want to compare each item in the list abf with each item of the value-lists in ref.
But... Under one condition, the program shall move on to the next value-list in ref (without checking the remaining items of the current value-list), and this is if the item of the value-list is 1 and the corresponding item in the list abf is 0.
To make it clear, here is one example:
the value-list of the key 'issue1' in the dict ref is [1, 1, 0, 0, 0, 1, 1, 1]. The list abf is [1, 1, 0, 1, 0, 1, 0, 0].
Now, I want to check each item of those two lists (the first item of the value-list of issue1 with the first item of the list abf, then the second item of issue1 with the second item of abf and so on...): As the first two items are 1 and 1 and the condition (see above) is not fulfilled, it shall go on to the next two items (which are again 1 and 1) and so on, UNTIL it gets to (in this case) the seventh items (which are 1 and 0). At this point it shall stop comparing value-list of issue1 with list abf and continue with comparing the next value-list (of issue2) with the list abf. I hope you get the idea!
Here is my code so far:
## ref is a dict with lists as values, abf is a list
ref = {'issue1': [1, 1, 0, 0, 0, 1, 1, 1],
'issue2': [1, 0, 0, 1, 0, 0, 0, 0],
'issue3': [0, 1, 0, 0, 1, 0, 0, 1]}
abf = [1, 1, 0, 1, 0, 1, 0, 0]
## getting the length of the lists in ref and abf ans save them in ref_total & abf_total
for key in ref:
[int(item) for item in ref[key]]
ref_total = len(ref[key])
abf_total = len(abf)
## check whether ref_total and abf_total has same value
if ref_total == abf_total:
for key, value in ref.items():
for j in value:
if (ref[key][j] == 1) and (abf[j] == 0): ## if item in ref is 1 and in abf is 0, go on to the next value-list
break
if j == abf_total-1: ## if he compared the whole value-list of the current key of ref with abf and the condition above did not occur, save the key of this value-list in resp!
resp = ref[key]
else:
resp = 'Length of strings varies!' ##if the lists don't have the same length
print resp ##let me know, which key "went through"
I am really looking forward to your responeses. The code does not work and I have no idea why!
I have added some notes as comment, but this should work:
## ref is a dict with lists as values, abf is a list
ref = {'issue1': [1, 1, 0, 0, 0, 1, 0, 1],
'issue2': [1, 0, 0, 1, 0, 0, 0, 0],
'issue3': [0, 1, 0, 0, 1, 0, 0, 1]}
abf = [1, 1, 0, 1, 0, 1, 1, 0]
# abf_total does not change during cycle. Calculate it outside.
abf_total = len(abf)
## getting the length of the lists in ref and abf ans save them in ref_total & abf_total
for key, items in ref.iteritems():
ref_total = len(items)
## check whether ref_total and abf_total has same value
if ref_total == abf_total:
# Here 'ref' screened the outside ref. Use 'i'
for i, value in enumerate(items):
if (items[i] == 1) and (abf[i] == 0): ## if item in ref is 1 and in abf is 0, go on to the next value-list
break
if i == abf_total-1:
# if he compared the whole value-list of the current key of ref with abf and the condition above did not occur, save the key of
this value-list in resp!
resp = "%s = %s" % (key, items)
else:
resp = 'Length of strings varies!' ##if the lists don't have the same length
print resp ##let me know, which key "went through"
The output is:
issue2 = [1, 0, 0, 1, 0, 0, 0, 0]
If I understand your requirement right, Python has that functionality built in. You can do this.
ref = {'issue1': [1, 1, 0, 0, 0, 1, 0, 1],
'issue2': [1, 0, 0, 1, 0, 0, 0, 0],
'issue3': [0, 1, 0, 0, 1, 0, 0, 1]}
abf = [1, 1, 0, 1, 0, 1, 1, 0]
abf == abf
# OUT: True
def findinref(d, abf):
for key, value in ref.items():
if value == abf:
return value
return None
findinref(ref, abf)
findinref(ref, [1,1,0,0,0,1,0,1])
# OUT: [1, 1, 0, 0, 0, 1, 0, 1]
There are few problems with your code, that I would like to point: -
for key in ref:
[int(item) for item in ref[key]]
To start with, your above loop is ambiguous. Its not doing anything, but just creating a list which is then ignored
Secondly,
ref_total = len(ref[key])
abf_total = len(abf)
The above assignment does not work, because you have placed it outside the for loop. Indentation problem.
if ref_total == abf_total:
for key, value in ref.items():
In the above code segment, rather than having your if condition first, and then the for loop, you should move your if condition in the for loop. So, for each key, value pair, check whether the len(value) == len(abf). If true, then continue with the inner for loop.
if (ref[key][j] == 1) and (abf[j] == 0)
This condition does not account for abf[j] = 1 and ref[key][j] = 0. Instead of checking the inequality, you can check the equality, and just take a negation of that. That would be easier. (EDIT: - Just noticed that, you just want to check it for that condition only. So you can ignore this change).
Also, your inner loop should not be for j in value. You cannot index on j then. Use for j in range(ref_list), to compare values at each index.
You can try out this code after the above changes: -
ref = {'issue1': [1, 1, 0, 0, 0, 1, 1, 1],
'issue2': [1, 0, 0, 1, 0, 0, 0, 0],
'issue3': [0, 1, 0, 0, 1, 0, 0, 1],
'issue4': [1, 1, 0, 1, 0, 1, 0, 0]}
abf = [1, 1, 0, 1, 0, 1, 0, 0]
abf_total = len(abf) # Since it will never change. Move it outside
for key, value in ref.items():
resp = ""
ref_total = len(value)
if ref_total == abf_total:
for j in range(ref_total):
if not (value[j] == abf[j]):
break
if j == abf_total-1:
resp = value
print resp
else:
resp = 'Length of strings varies!' ##if the lists don't have the same length
OUTPUT : -
[1, 1, 0, 1, 0, 1, 0, 0]
thank you all very very much, you are really awesome! I didn't expect that much feedback!! You really helped me a lot. I went for Rohit Jain's solution - thank you very much Rohit!! Here is the complete code (if there is space for improvements, don't hesitate to critizise me! any feedback is really appreciated!!)
ref = {'issue1': [1, 1, 0, 0, 0, 1, 1, 1],
'issue2': [1, 0, 0, 1, 0, 0, 0, 0],
'issue3': [0, 1, 0, 0, 1, 0, 0, 1]}
abf = [1, 1, 0, 1, 0, 1, 0, 0]
abf_total = len(abf)
for key, value in ref.items():
ref_total = len(ref[key])
if ref_total == abf_total:
i = -1
for j in value:
i += 1
if (j == 1) and (abf[i] == 0):
break
if i == len(abf)-1:
resp = key
else:
resp = 'Length of strings varies!'
print resp