I have an array a = [4,3,2,1]
What I am trying to achieve is that I need a single value on subtracting the elements in the array that is 4-3-2-1.
I tried the below this using for loop but it does not seem to work. I don't seem to get the right value on execution.
def sub_num(arr):
difference = arr[0]
n = len(arr)
print(n)
print(i)
for i in n: difference = arr[n] - arr[n-1]
return(difference)
If you have a list a:
a = [4, 3, 2, 1]
And wish to get the result of 4 - 3 - 2 - 1, you can use functools.reduce.
>>> from functools import reduce
>>> a = [4, 3, 2, 1]
>>> reduce(int.__sub__, a)
-2
>>>
You can solve with nested lists:
b = sum([a[0],*[-x for x in a[1:]]])
Simpler solution without for:
Since 4-3-2-1 is equal to 4-(3+2+1):
a[0]-sum(a[1:])
You could modify your code like this
def sub_num(arr):
difference = arr[0]
n = len(arr)
print(n)
for i in range(1,n):
difference = difference - arr[i]
return difference
Note:
Printing value of i without defining it is not possible
I have two lists
a = [1, 4, 12]
b = [2, 13]
I want to know if values in list b are between two values in list a
So, in this case, 2 will fall between 1 and 4. 13 will not fall between any numbers.
I have tried bisect function, but I couldn't get it work. I was able to use it with a single value and a list, but not two lists.
Maybe there's some subtlety that I do not get, but unless I am mistaken, you only have to check whether the elements are between the min and max from a. This is independent of whether the elements in a are sorted, or whether the values from b have to be between consecutive values from a. As long as they are between the min and max, there has to be a "segment" in a those values are in.
>>> a = [1, 4, 12]
>>> b = [2, 13]
>>> n, m = min(a), max(a)
>>> [n < x < m for x in b]
[True, False]
That is, of course, only if (a) you do not need which numbers they are in between, and (b) if not all values in b have to be in the same interval.
If you think I missed something, please comment.
It really depends on what you want it to return. I wrote a code that will return the first pattern that it finds, but with some changes I'm sure it would not be difficult to return all combinations.
def get_between(a, b):
a, b = sorted(a), sorted(b)
for b_value in b:
smaller = None
greater = None
for a_value in a:
if b_value > a_value:
smaller = a_value
elif b_value < a_value:
greater = a_value
if smaller and greater:
return f"{b_value} is between {smaller} and {greater}"
return "There is no such combination"
a = [1, 4, 12]
b = [2, 13]
print(get_between(a, b))
The output on that case will be 2 is between 1 and 4, but you can adapt the return value to be whatever you want.
You can keep two running indices to get a list of all elements that fall between values:
def get_between(arr1, arr2):
# first sort the arrays
arr1 = sorted(arr1)
arr2 = sorted(arr2)
# keep two indices into them
i1 = 0
i2 = 0
# keep track of the values between two values
ret = []
while i1 < len(arr1) - 1 and i2 < len(arr2):
# we're too small to be between a value
# so we should increase the second index
if arr2[i2] < arr1[i1]:
i2 += 1
# we're too large to be between a value
# so we should increase the first index
elif arr2[i2] > arr1[i1 + 1]:
i1 += 1
# we are between a value
# so we should append to the return array
# and move on to the next element
else:
ret.append(arr2[i2])
i2 += 1
return ret
get_between([1, 4, 12], [2, 8, 13]) # [2, 8]
If you don't care much about performance, here's a pythonic solution-
def betwn(rangelist, valuelist):
# Get list of all ranges between each consecutive number of rangelist
rgs = [range(rangelist[n], rangelist[n + 1]) for n in range(len(rangelist) - 1)]
# A function to check whether a given element exists between 2 consecutive numbers of rangelist
verifyfunc = lambda e: any(e in r for r in rgs)
# Return the qualifying elements from valuelist
return [e for e in valuelist if verifyfunc(e)]
Output
>>> betwn([1, 4, 12], [2, 13])
[2]
I don't get how a "for" loop that iterates through the elements of a list can be out of range.
First part seems to be okay as I can print it.
import random
def random_list(n):
l = []
for i in range(0,n):
l.append(random.randint(0,n))
return l
def maximum(n):
x = 0
b = random_list(n)
for i in b:
if b[i] > x:
x = b[i]
print (maximum(10))
This:
for i in b:
if b[i] > x:
x = b[i]
Iterates over the elements of b, not the indices. Change it to
for i in b:
if i > x:
x = i
You also need to return something from your function, probably x.
Considering that you know how to iterate over a list in python, the error could be due to randint, which generates an integer in the interval [low, high]. This means high is a possible output, while the highest index in your program is high - 1.
For example,
random.randint(0, 0)
gives 0.
Similarly, random.randint(10) can return 10.
If you don't understand how to iterate over a list in Python, consider a simple example:
Take the list below:
myList = [1, 3, 5, 7, 9]
Now, there are two ways to iterate over the list:
Directly accessing elements:
for element in myList:
print(element, end=" ")
This gives the output:
1 3 5 7 9
Accessing elements using indices
for idx in range(len(myList)):
print(idx, ":", myList[idx], end=" ")
This gives the output:
0:1 1:3 2:5 3:7 4:9
I'd like to count how many times a big list contains elements in specific order. So for example if i have elements [1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5] and i'd like to know how many times [1,2,3] are next to each other (answer is 4 in this case).
I was thinking on checking the indexes of number '3' (so currently it'd return [2,7,12,17]. Then i would iterate over that list, take elements in positions described in the list and check two positions in front of it. If they match '1' and '2' then add 1 to counter and keep looking. I believe this solution isn't really efficient and does not look nice, would there be a better solution?
Here's a generalized solution that works for subsequences of any size and for elements of any type. It's also very space-efficient, as it only operates on iterators.
from itertools import islice
def count(lst, seq):
it = zip(*(islice(lst, i, None) for i in range(len(seq))))
seq = tuple(seq)
return sum(x == seq for x in it)
In [4]: count(l, (1, 2, 3))
Out[4]: 4
The idea is to create a sliding window iterator of width len(seq) over lst, and count the number of tuples equal to tuple(seq). This means that count also counts overlapping matches:
In [5]: count('aaa', 'aa')
Out[5]: 2
For lists of ints, you could convert to strings and then use the count method:
>>> x = [1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5]
>>> y = [1,2,3]
>>> s = ',' + ','.join(str(i) for i in x) + ','
>>> t = ',' + ','.join(str(i) for i in y) + ','
>>> s.count(t)
4
If the items in the list contained strings which contain commas, this method could fail (as #schwobaseggl points out in the comments). You would need to pick a delimiter known not to occur in any of the strings, or adopt an entirely different approach which doesn't reduce to the string count method.
On Edit: I added a fix suggested by #Rawing to address a bug pointed out by #tobias_k . This turns out to be a more subtle problem than it first seems.
x = [1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5]
y = [1,2,3]
count = 0
for i in range(len(x)-len(y)):
if x[i:i+len(y)] == y:
count += 1
print(count)
You could iterate the list and compare sublists:
In [1]: lst = [1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5]
In [2]: sub = [1,2,3]
In [3]: [i for i, _ in enumerate(lst) if lst[i:i+len(sub)] == sub]
Out[3]: [0, 5, 10, 15]
Note, however, that on a very large list and sublist, this is pretty wasteful, as it creates very many slices of the original list to compare against the sublist. In a slightly longer version, you could use all to compare each of the relevant positions of the list with those of the sublist:
In [5]: [i for i, _ in enumerate(lst) if all(lst[i+k] == e for k, e in enumerate(sub))]
Out[5]: [0, 5, 10, 15]
This strikes me as the longest common subsequence problem repeated every time until the sequence returned is an empty list.
I think that the best that you can do in this case for an efficient algorithm is O(n*m) where n is the number of elements in your big list and m is the number of elements in your small list. You of course would have to have an extra step of removing the small sequence from the big sequence and repeating the process.
Here's the algorithm:
Find lcs(bigList, smallList)
Remove the first occurrence of the smallList from the bigList
Repeat until lcs is an empty list
Return the number of iterations
Here is an implementation of lcs that I wrote in python:
def lcs(first, second):
results = dict()
return lcs_mem(first, second, results)
def lcs_mem(first, second, results):
key = ""
if first > second:
key = first + "," + second
else:
key = second + "," + first
if len(first) == 0 or len(second) == 0:
return ''
elif key in results:
return results[key]
elif first[-1] == second[-1]:
result = lcs(first[:-1], second[:-1]) + first[-1]
results[key] = result
return result
else:
lcsLeft = lcs(first[:-1], second)
lcsRight = lcs(first, second[:-1])
if len(lcsLeft) > len(lcsRight):
return lcsLeft
else:
return lcsRight
def main():
pass
if __name__ == '__main__':
main()
Feel free to modify it to the above algorithm.
One can define the efficiency of solution from the complexity. Search more about complexity of algorithm in google.
And in your case, complexity is 2n where n is number of elements.
Here is the solution with the complexity n, cause it traverses the list only once, i.e. n number of times.
def IsSameError(x,y):
if (len(x) != len(y)):
return False
i = 0
while (i < len(y)):
if(x[i] != y[i]):
return False
i += 1
return True
x = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
y = [1, 2, 3]
xLength = len(x)
yLength = len(y)
cnt = 0
answer = []
while (cnt+3 < xLength):
if(IsSameError([x[cnt], x[cnt+1], x[cnt+2]], y)):
answer.append(x[cnt])
answer.append(x[cnt+1])
answer.append(x[cnt + 2])
cnt = cnt + 3
else:
cnt = cnt + 1
print answer
If i had a list of numbers and some maybe negative, how would i ensure all numbers in my list were positive? I can covert the items in the list to integers thats no problem.
Another question, I want to compare items in my list to an integer value say 'x' and sum all the values in my list that are less than x.
Thank you.
If you have a list Ns of numbers (if it's a list of strings as in several similar questions asked recently each will have to be made into an int, or whatever other kind of number, by calling int [[or float, etc]] on it), the list of their absolute values (if that's what you mean by "ensure") is
[abs(n) for n in Ns]
If you mean, instead, to check whether all numbers are >= 0, then
all(n >= 0 for n in Ns)
will give you a bool value respecting exactly that specification.
The sum of the items of the list that are <x is
sum(n for n in Ns if n < x)
Of course you may combine all these kinds of operations in one sweep (e.g. if you need to take the abs(n) as well as checking if it's < x, checking if it's >= 0, summing, whatever).
# input list is named "lst"
pos_list = [int(a) for a in lst if int(a) > 0]
# And num 2 (notice generator is used instead of list)
return sum(a for a in lst if a < x)
Answer / First part:
>>> a = [1, 2, -3, 4, 5, 6]
>>> b = [1, 2, 3, 4, 5, 6]
>>> max(map(lambda x: x < 0, a))
False
>>> max(map(lambda x: x < 0, b))
True
Or just use min:
>>> min(a) < 0
True
>>> min(b) < 0
False
Second part:
>>> x = 3
>>> sum(filter(lambda n: n < x, a))
>>> 0
>>> sum(filter(lambda n: n < x, b))
>>> 3
If I understand correctly your question, I guess you are asking because of some class about functional programming.
In this case, what you are asking for can be accomplished with functional programming tools available in Python.
In particular, the first point can be solved using filter, while the second with map and reduce (or, better, with map and sum).
>>>mylist = [1,2,3,-2]
>>>any(item for item in mylist if item < 0)
True
>>>mylist.pop()
-2
>>>any(item for item in mylist if item < 0)
False
answers your first question.
>>> x = 3
>>> sum(item for item in mylist if item < x)
3
answers your second question.