How would I find the exact middle of a python list?
aList = [1,2,3,4,5]
middle = findMiddle(aList)
print middle
This is just an example of a function that would be able to find the middle of any list, is this something you can do using list comprehension?
Edit: This is different than taking out the middle point because I would like to just print out the middle value, if the list is odd I would like to return both the middle values like the accepted answer. Not getting the median like the other question has asked and getting the average of the two values.
Something like this would do:
aList = [1,2,3,4,5]
#minus 1 because the first element is index 0
middleIndex = (len(aList) - 1)/2
print middleIndex
print aList[middleIndex]
Why would you use a list comprehension? A list comprehension only knows about any one member of a list at a time, so that would be an odd approach. Instead:
def findMiddle(input_list):
middle = float(len(input_list))/2
if middle % 2 != 0:
return input_list[int(middle - .5)]
else:
return (input_list[int(middle)], input_list[int(middle-1)])
This one should return the middle item in the list if it's an odd number list, or a tuple containing the middle two items if it's an even numbered list.
Edit:
Thinking some more about how one could do this with a list comprehension, just for fun. Came up with this:
[lis[i] for i in
range((len(lis)/2) - (1 if float(len(lis)) % 2 == 0 else 0), len(lis)/2+1)]
read as:
"Return an array containing the ith digit(s) of array lis, where i is/are the members of a range, which starts at the length of lis, divided by 2, from which we then subtract either 1 if the length of the list is even, or 0 if it is odd, and which ends at the length of lis, divided by 2, to which we add 1."
The start/end of range correspond to the index(es) we want to extract from lis, keeping in mind which arguments are inclusive/exclusive from the range() function in python.
If you know it's going to be an odd length list every time, you can tack on a [0] to the end there to get the actual single value (instead of an array containing a single value), but if it can or will be an even length list, and you want to return an array containing the two middle values OR an array of the single value, leave as is. :)
Take the length of the list, cut that in half and access whatever the list at that index point.
Are you expecting something like
def findMiddle(list):
l = len(list)
if l/2:
return (list[l/2-1]+list[l/2])/2.0
else:
return list[(l/2-1)/2]
Related
this is the challenge :
This next function will give us the values from a list at every odd index. We will need to accept a list of numbers as an input parameter and loop through the odd indices instead of the elements. Here are the steps needed:
Define the function header to accept one input which will be our list of numbers
Create a new list which will hold our values to return
Iterate through every odd index until the end of the list
Within the loop, get the element at the current odd index and append it to our new list
Return the list of elements which we got from the odd indices.
and This is my solution :
def odd_indices(lst):
odd_list = []
index = 1
while index % 2 != 0 and index < len(lst):
odd_list.append(lst[index])
index +=1
return odd_list
print(odd_indices([4, 3, 7, 10, 11, -2]))
This doesnt return [3] only . can you help me figure out why ?
You check the parity in the loop control, instead of inside the loop.
I need a help. I want to chunk my list with float numbers into sublists to compare two decimal numbers to see if the difference between the consecutive numbers are in the range 10. To more specific, my expectation is to split them for example, those numbers from 70-80 to be in a list, from 80-90 to be in another list, and so on.
Firstly, I sorted my list and then tried to compare two elements, but the result is different from that I want.
Here is my attempt to compare numbers:
mylist = [125.90720268, 122.08697428, 86.70855817, 82.68482956, 75.99304643, 71.92440719, 80.92440719]
chunked_list = []
sort_list = sorted(mylist, key = lambda x:float(x))
curr = [sort_list[0]]
print("sort_list = ", sort_list)
for x in sort_list[1:]:
if abs(x - curr[-1]) < 10:
chunked_list.append(curr)
curr = [x]
else:
curr.append(x)
chunked_list.append(curr) ```
The result is:
[[71.92440719],
[75.99304643],
[80.92440719],
[82.68482956],
[86.70855817, 122.08697428],
[125.90720268]]
while I want to have this result:
[[71.92440719, 75.99304643], [80.92440719, 82.68482956, 86.70855817], [122.08697428, 125.90720268]]
Also, I tried to use math.isclose() function to compare two decimal numbers, but I failed again. I really appreciate that someone tells me where I make a mistake.
You can use itertools.pairwise (or its equivalent recipe if you're using Python of version < 3.10) to iterate through the list in adjacent pairs, and append to the output list a new sub-list if the difference between the pair is greater than 10 while keep appending to the last sub-list the current item:
from itertools import pairwise
output = []
for a, b in pairwise(sorted(mylist)):
if not output or b - a > 10:
output.append([] if output else [a])
output[-1].append(b)
Given your sample input, output becomes:
[[71.92440719, 75.99304643, 80.92440719, 82.68482956, 86.70855817], [122.08697428, 125.90720268]]
Demo: https://replit.com/#blhsing/ImperturbableCrushingAdministrator
EDIT: Since you updated your question with a revised requirement that the numbers should be grouped in multiples of 10, you can append a new sub-list to the output list when the current item divided by 10 is different from the first item of the last sub-list divided by 10:
output = []
for i in sorted(mylist):
if not output or i // 10 != output[-1][0] // 10:
output.append([])
output[-1].append(i)
output becomes:
[[71.92440719, 75.99304643], [80.92440719, 82.68482956, 86.70855817], [122.08697428, 125.90720268]]
Demo: https://replit.com/#blhsing/ElaborateUsedRotation
In this code:
x = [0,1,2]
for item in range(len(x)):
print x[item]
The result printed is:
0 1 2
What does x[item] do? What does it mean?
x is a list. item is index that ranges from 0 to length of list x -1 .
x[item] access the value at index item in list x.
X is variable that contains 3 values in it, this type of variables are called array or list that can hold multiple values instead of single.
To access the values of x you need to access index of this variable which starts from 0 and ends to n-1 where n is numbers of values your variable has.
For e.g you have 3 values here so your n will be (3-1) 2 which is also called as length or size interchangeably.
So to access values of x , we defined a temporary indexer which is 'item'.
x[items] goes from 0 to n-1 values and simply print them .
Hope you got the concept.
x is a list that has three values in it. Every time the loop runs it will set the variable 'item' to the current number of times the loop has run (since there are three values in the list it will be 0, then 1, then 2). When printing x[0], it will print the first item in the list. So when you print x[item], it will print the 1st item in the list, then the 1st, then 2nd, then third.
Read up on lists and for loops to learn more.
I'm solving a puzzle that takes in a list, loops through each index and sums the values to the left and to the right of the current index. If it finds an index at which the sum of the values to its left are equal to the sum of the values to its right, then return that index.
For example:
[1,2,3,4,3,2,1]
If I am at index 3 (value 4), we see that the sum of values of elements to its left and right are equal.
(1 + 2 + 3) = (3 + 2 + 1).
However, when the input is a list of negative values, it returns a negative index. This is my code:
def get_equal_sum(list):
for i in list:
if sum(list[:i]) == sum(list[i+1:]):
print i
list = [1,2,3,4,3,2,1]
get_equal_sum(list)
>>> 3
list = [-1,-2,-3,-4,-3,-2,-1]
get_equal_sum(list)
>>> -4
Why is it returning -4 and not 3?
Thank you!
When you do
for i in list:
if sum(list[:i]) == sum(list[i+1:]):
i is not the index of the list but the value. The fact that it doesn't crash with IndexError when you feed the slices with negative values is because negative indexing is supported in python (indexes from the end of the list) as long as absolute value is in range (which is the case here). That's probably why you missed that.
If you want indexes you have to use enumerate for instance:
for i,_ in enumerate(l):
if sum(l[:i]) == sum(l[i+1:]):
(and change list to l because list is the list type)
Note the i,_ notation to unpack index/value and discard the value which isn't needed here. You could also go with the classical:
for i in range(len(l)):
for i in list:
...
This goes through the values of list, not the index (hence you why you get -4), to go through index you must use xrange (or range for python 3) over the len(list)
for i in xrange(len(list)):
...
or use enumerate(list). enumerate returns a tuple of the index value pair on any iteratable object, so you would index over a list like this:
for index, value in enumerate(list):
...
In this situation index is likely your i. Additionally, you do not want to shadow names already used by python itself (ie list or max, or min abs etc...) this will overwrite those variables to be what you assign them to in your program. For example, list is no longer a function that can create a list from list(iterable), but is now what ever you assign it to, you can no longer use it the default python way. Here is a list of python 2.7 built function in names
Because -4 is at index -4. You can have negative indices in Python with index -1 being the last element in a list.
I have list of numbers as follows -
L = [ 1430185458, 1430185456, 1430185245, 1430185246, 1430185001 ]
I am trying to determine which numbers are within range of "2" from each other. List will be in unsorted when I receive it.
If there are numbers within range of 2 from each other I have to return "1" at exact same position number was received in.
I was able to achieve desired result , however code is running very slow. My approach involves sorting list, iterating it twice taking two pointers and comparing it successively. I will have millions of records coming as seperate lists.
Just trying to see what is best possible approach to address this problem.
Edit - Apology as I was away for a while. List can have any number of elements in it ranging from 1 to n. Idea is to return either 0 or 1 in exact same position number was received. I can not post actual code I implemented but here is pseudo code.
a. create new list as list of list with second part as 0 for each element. We assume that there are no numbers within range of 2 of each other.
[[1430185458,0], [1430185456,0], [1430185245,0], [1430185246,0], [1430185001,0]]
b. sort original list
c. compare first element to second, second to third and so on until end of list is reached and whenever difference is less than or equal to 2 update corresponding second elements in step a to 1.
[[1430185458,1], [1430185456,1], [1430185245,1], [1430185246,1], [1430185001,0]]
The goal is to be fast, so that presumably means an O(N) algorithm. Building an NxN difference matrix is O(N^2), so that's not good at all. Sorting is O(N*log(N)), so that's out, too. Assuming average case O(1) behavior for dictionary insert and lookup, the following is an O(N) algorithm. It rips through a list of a million random integers in a couple of seconds.
def in_range (numbers) :
result = [0] * len(numbers)
index = {}
for idx, number in enumerate(numbers) :
for offset in range(-2,3) :
match_idx = index.get(number+offset)
if match_idx is not None :
result[match_idx] = result[idx] = 1
index[number] = idx
return result
Update
I have to return "1" at exact same position number was received in.
The update to the question asks for a list of the form [[1,1],[2,1],[5,0]] given an input of [1,2,5]. I didn't do that. Instead, my code returns [1,1,0] given [1,2,5]. It's about 15% faster to produce that simple 0/1 list compared to the [[value,in_range],...] list. The desired list can easily be created using zip:
zip(numbers,in_range(numbers)) # Generator
list(zip(numbers,in_range(numbers))) # List of (value,in_range) tuples
I think this does what you need (process() modifies the list L). Very likely it's still optimizable, though:
def process(L):
s = [(v,k) for k,v in enumerate(L)]
s.sort()
j = 0
for i,v_k in enumerate(s):
v = v_k[0]
while j < i and v-s[j][0]>2:
j += 1
while j < i:
L[s[j][1]] = 1
L[s[i][1]] = 1
j += 1