例如我有一个无序的值列表[10,20,50,200,100,300,250,150]
我有这个代码,它返回下一个更大的值:
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])
e.g。如果temp = 55,它将返回'100'。
但我怎样才能获得较小的价值?那是如何让它返回'50'?
谢谢。
编辑 - 现在正在运作
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 + "° 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"
答案 0 :(得分:18)
更好更快(代码和cpu方式)的方法是使用bisect模块进行二进制搜索,但为此您需要先对列表进行排序,这是示例用法:
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]
输出:
Greater than target 100
Smaller than or equal to target 50
此外,您需要检查返回的索引,如果它是0
,则表示您已通过目标低于最低值
答案 1 :(得分:4)
修改:啊,我使用templist
代替list
- 因此造成了混乱。我并不是说它是一个单行的功能;你仍然需要进行转换。 (当然,正如Mike DeSimone正确地指出的那样,使用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
感谢Mike建议在空列表的情况下返回None
- 我喜欢这样。
你可以更加简短地缩短它:
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
答案 2 :(得分:2)
nextHighest = lambda seq,x: min([(i-x,i) for i in seq if x<=i] or [(0,None)])[1]
nextLowest = lambda seq,x: min([(x-i,i) for i in seq if x>=i] or [(0,None)])[1]
以下是它的工作原理:查看nextHighest
,min的参数是列表推导,它计算列表中每个值与输入x之间的差异,但仅适用于那些值&gt; = x。由于您需要实际值,因此我们需要列表元素以包含值与实际值的差异。元组按值从左到右进行比较,因此序列中每个值i
的元组变为(i-x,i)
- 最小元组将具有[1]
'中的实际值元素。
如果输入x值超出seq中的值范围(或者如果seq只是空),那么列表推导将给我们一个空列表,这将在min
中引发一个ValueError。如果发生这种情况,我们会在or [(0,None)]
的参数中添加min
字词。如果列表推导为空,则它将评估为False,在这种情况下,min将查看包含单个元组(0,None)
的序列。在这种情况下,[1]
'元素为None,表示seq中没有高于x的元素。
以下是一些测试用例:
>>> 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
答案 3 :(得分:1)
让无序列表为myList
:
answer = max(x for x in myList if x < temp)
答案 4 :(得分:0)
如果我理解正确,你想要的最大价值低于你的目标;例如在你的例子中,如果你的目标是55,你想要50,但如果你的目标是35,你想要20。以下函数应该这样做:
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)
如果您需要单步执行这些值,可以使用generator连续获取值:
def next_lesser(l, target):
for n in l:
if n < target:
yield str(n)
这些都可以在一个简单的程序中正常工作。
答案 5 :(得分:0)
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)