Python: how to find a value in a list less than the target

For example, I have an unordered list of values ​​[10, 20, 50, 200, 100, 300, 250, 150]

I have this code that returns the following larger value:

def GetNextHighTemp(self, temp, templist): target = int(temp) list = [] for t in templist: if t != "": list.append(int(t)) return str(min((abs(target - i), i) for i in list)[1]) 

eg. If temp = 55, it will return "100".

But how can I get a lower value? Here's how to get him back to 50?

Thanks.

EDIT - now works

 def OnTWMatCurrentIndexChanged(self): self.ClearTWSelectInputs() material = self.cb_TW_mat.currentText() temp = self.txt_design_temp.text() if material != "": Eref = self.GetMaterialData(material, "25", "elast") if Eref and Eref != "": Eref = str(float(Eref) / 1000000000) self.txt_TW_Eref.setText(Eref) else: self.txt_TW_Eref.setText("194.8") self.ShowMsg("No temperature match found for E<sub>ref</sub> in material data file. Value of 194.8 GPa will be used.", "blue") if material != "" and temp != "": if self.CheckTWTemp(material, temp): dens = self.GetMaterialData(material, temp, "dens") self.txt_TW_dens.setText(dens) elast = self.GetMaterialData(material, temp, "elast") elast = str(float(elast) / 1000000000) self.txt_TW_Et.setText(elast) stress = self.GetMaterialData(material, temp, "stress") stress = str(float(stress) / 1000000) self.txt_TW_stress_limit.setText(stress) else: self.ShowMsg("No temperature match found for " + temp + "&#x00B0; C in material data file. Extrapolated data will be used where possible or add new material data.", "blue") dens = self.GetExtrapolatedMaterialData(material, temp, "dens") self.txt_TW_dens.setText(dens) elast = self.GetExtrapolatedMaterialData(material, temp, "elast") elast = str(float(elast) / 1000000000) self.txt_TW_Et.setText(elast) stress = self.GetExtrapolatedMaterialData(material, temp, "stress") stress = str(float(stress) / 1000000) self.txt_TW_stress_limit.setText(stress) else: self.ClearTWSelectInputs() def CheckTWTemp(self, matvar, tempvar): for material in self.materials: if material.attrib["name"] == matvar: temps = material.getiterator("temp") for temp in temps: if int(temp.text) == int(tempvar): return True return False def GetMaterialData(self, matvar, tempvar, tag): for material in self.materials: if material.attrib["name"] == matvar: temps = material.getiterator("temp") for temp in temps: if temp.text == tempvar: value = temp.find(tag) return value.text def GetExtrapolatedMaterialData(self, matvar, tempvar, tag): try: templist = QStringList() for material in self.materials: if material.attrib["name"] == matvar: temps = material.getiterator("temp") for temp in temps: templist.append(temp.text) templist.sort() target = int(tempvar) x1 = max(int(t) for t in templist if t != '' and int(t) < target) x2 = min(int(t) for t in templist if t != '' and int(t) > target) y1 = float(self.GetMaterialData(matvar, str(x1), tag)) y2 = float(self.GetMaterialData(matvar, str(x2), tag)) x = target y = y1 - ((y1 - y2) * (x - x1) / (x2 - x1)) return str(y) except Exception, inst: return "0" 
+4
source share
6 answers

Edit : Ah, I used templist instead of list - hence the confusion. I did not mean that this is a one-line function; you still have to do conversions. (Of course, as Mike De Simon rightly points out, using a list as a variable name is a terrible idea! So I had a good reason to be confused. :)

To be more explicit, here is a slightly simplified version of the function (fixed for correctly testing an empty list):

 def GetNextHighTemp(self, temp, templist): templist = (int(t) for t in templist if t != '') templist = [t for t in templist if t < int(temp)] if templist: return max(templist) else: return None # or raise an error 

Thanks to Mike for the offer to return None if the list is empty - I like it.

You can cut it even further by:

 def GetNextHighTemp(self, temp, templist): try: return str(max(int(t) for t in templist if t != '' and int(t) < int(temp))) except ValueError: return None # or raise a different error 
+4
source

A better and much faster (code and cpu wise) way is to use the bisect module, which performs a binary search, but for this you need to sort the list first, here is an example of use:

 import bisect mylist = [10, 20, 50, 200, 100, 300, 250, 150] mylist.sort() index = bisect.bisect(mylist, 55) print "Greater than target", mylist[index] print "Smaller than or equal to target", mylist[index-1] 

output:

 Greater than target 100 Smaller than or equal to target 50 

You will also need to check the returned index, if it is 0 , it means that you have passed the target below the minimum

+15
source
 nextHighest = lambda seq,x: min([(ix,i) for i in seq if x<=i] or [(0,None)])[1] nextLowest = lambda seq,x: min([(xi,i) for i in seq if x>=i] or [(0,None)])[1] 

Here's how it works: looking at nextHighest , the min argument is a list comprehension that computes the differences between each value in the list and input x, but only for those> = x values. Since you want the actual value, we need list items that include both the difference in value and the actual value. Tuples are compared by value from left to right, so the tuple for each value i in the sequence becomes (ix,i) - the minimum tuple will have the actual value in the element [1] 'th.

If the input value of x is outside the range of values ​​in seq (or if seq is just empty), then understanding the list will give us an empty list that raises the value of ValueError to min . In case this happens, we will add the member or [(0,None)] inside the argument to min . If the list comprehension is empty, it will be evaluated as False, in which case min will look at a sequence containing one tuple (0,None) . In this case, the [1] 'th element is None, which indicates the absence of elements in seq higher than x.

Here are some test cases:

 >>> t = [10, 20, 50, 200, 100, 300, 250, 150] >>> print nextHighest(t,55) 100 >>> print nextLowest(t,55) 50 >>> print nextHighest([],55) None >>> print nextLowest([],55) None >>> print nextHighest(t,550) None 
+2
source

If I understand you correctly, you want the greatest value to be less than your goal; for example, in your example, if your goal is 55, you need 50, but if your goal is 35, you need 20. The following function should do this:

 def get_closest_less(lst, target): lst.sort() ret_val = None previous = lst[0] if (previous <= target): for ndx in xrange(1, len(lst) - 1): if lst[ndx] > target: ret_val = previous break else: previous = lst[ndx] return str(ret_val) 

If you need to go through these values, you can use generator to get the following values:

 def next_lesser(l, target): for n in l: if n < target: yield str(n) 

Both of them worked correctly from a simple program.

0
source
 a=[4,3,8,2,5] temp=4 def getSmaller(temp,alist): alist.sort() for i in range(len(alist)): if(i>0 and alist[i]==temp): print alist[i-1] elif(i==0 and alist[i]==temp): print alist[i] getSmaller(temp,a) 
0
source

Let the unordered list myList :

answer = max(x for x in myList if x < temp)

0
source

Source: https://habr.com/ru/post/1344213/


All Articles