如何从 bin 中分配整数值
How to assign integer value from bins
我正在尝试找到一种 pythonic 方法来根据变量所在的位置分配数值。即:
variable = 23
if variable < -100:
return_value = -15
elif variable <= -5:
return_value = -4
elif variable <= 5:
return_value = 18
else:
return_value = 88
我当然可以创建一个包含 buckets/values 的列表,并在找到正确值时遍历 return:
bucket_values = [(-100, -15), (-5, -4), (5, 18)]
default = 88
variable = 100
for lower_bound, value in bucket_values:
if variable < lower_bound:
return_value = value
break
else:
return_value = default
但随后我需要检查下限和上限以及相等性,即如果这是循环的第一次迭代,我必须检查是否为劣质 (<),然后我必须检查下一个循环是否为劣质 & 等于 (< =).
我正在寻找这样的东西 (Ruby):
buckets = [
[:<, -90, -57],
[:<=, 5, -10],
[:<=, 10, 3],
[:>, 60, 40]]
# Pass bucket to a method
我的问题是:
是否有一种 pythonic 方法可以使用变量边界和值来执行此操作?
我觉得这很 pythonic,但我不推荐它
>>> variable = 23
>>> return_value = -5 if variable<-100 else -4 if variable<=-4 else 18 if variable<= 5 else 88
>>> print(return_value)
88
请注意 88
是默认值。
编辑
您可以创建一个基于与上述 if... else
相同概念的函数。该函数将是这样的:
def pythonic(variable, bucket_values, default):
for k,v in bucket_values:
return_value = v if variable<k else "---"
if return_value != "---":
return return_value
return default
你可以这样使用它:
>>> variable = 23
>>> bucket_values = [(-100, -15), (-5, -4), (5, 18)]
>>> print(pythonic(variable, bucket_values, 88))
88
>>> variable = 1
>>> print(pythonic(variable, bucket_values, 88))
18
如果我理解得很好,对于每个 "bucket" 你都有一个间隔。要检查值是否属于某个区间,您可以定义一个函数:
def check_value(value, interval):
if value in range(interval[0], interval[1]+1):
print('Value ', value)
print('Interval ', interval)
else:
pass
现在只需遍历间隔列表以查找值所属的位置:
for interval in list_of_intervals:
check_value(value, interval)
使用模块 operator
非常简单。这是一个例子:
>>> import operator
>>> bucket = (operator.ge, -100, operator.le, -5)
>>> def in_bucket(value, bucket): return bucket[0](value, bucket[1]) and bucket[2](value, bucket[3])
...
>>> in_bucket(-101, bucket)
False
>>> in_bucket(-100, bucket)
True
>>> in_bucket(-5, bucket)
True
>>> in_bucket(-4, bucket)
False
但是您可以通过定义更通用的结构来做得更好:
>>> conditions = ((operator.ge, -100), (operator.le, -5))
>>> def match_conditions(value, conditions): return all(c[0](value, c[1]) for c in conditions)
...
>>> match_conditions(-101, conditions)
False
>>> match_conditions(-100, conditions)
True
>>> match_conditions(-5, conditions)
True
>>> match_conditions(-4, conditions)
False
all
运算符 returns 为真当且仅当满足所有条件。 bucket
和 conditions
之间的主要区别在于您可以添加与边界无关的条件,例如值必须是对:
>>> conditions = ((operator.ge, -100), (operator.le, -5), (lambda v, _: v%2==0, None))
>>> match_conditions(-7, conditions)
False
>>> match_conditions(-6, conditions)
True
>>> match_conditions(-5, conditions)
False
现在你可以用字典来总结你的条件(你给的第一个例子):
>>> value_by_conditions = {
... ((operator.lt, -100),): -15,
... ((operator.ge, -100), (operator.le, -5)): -4,
... ((operator.gt, -5), (operator.le, 5)): 18,
... ((operator.gt, 5),): 88,
... }
>>> next((v for cs, v in value_by_conditions.items() if match_conditions(23, cs)), None)
88
>>> next((v for cs, v in value_by_conditions.items() if match_conditions(-101, cs)), None)
-15
>>> next((v for cs, v in value_by_conditions.items() if match_conditions(-100, cs)), None)
-4
备注:
- 我使用了元组,因为列表不可散列(因此不能用作字典键);
next((x for x in xs if <test>), None)
取 xs
中第一个通过测试的元素。如果没有元素通过测试,它 returns 默认值 None
;
- 在旧版本的 Python (< 3.7) 中,您无法保证测试的顺序。如果您有重叠条件,这一点很重要。
- 这显然是次优的,因为你先测试 if
value < 100
然后 if value >= 100
,等等
这真的是pythonic吗?我不确定。看看 https://www.python.org/dev/peps/pep-0020/ 来提出自己的想法。
我正在尝试找到一种 pythonic 方法来根据变量所在的位置分配数值。即:
variable = 23
if variable < -100:
return_value = -15
elif variable <= -5:
return_value = -4
elif variable <= 5:
return_value = 18
else:
return_value = 88
我当然可以创建一个包含 buckets/values 的列表,并在找到正确值时遍历 return:
bucket_values = [(-100, -15), (-5, -4), (5, 18)]
default = 88
variable = 100
for lower_bound, value in bucket_values:
if variable < lower_bound:
return_value = value
break
else:
return_value = default
但随后我需要检查下限和上限以及相等性,即如果这是循环的第一次迭代,我必须检查是否为劣质 (<),然后我必须检查下一个循环是否为劣质 & 等于 (< =).
我正在寻找这样的东西 (Ruby):
buckets = [
[:<, -90, -57],
[:<=, 5, -10],
[:<=, 10, 3],
[:>, 60, 40]]
# Pass bucket to a method
我的问题是: 是否有一种 pythonic 方法可以使用变量边界和值来执行此操作?
我觉得这很 pythonic,但我不推荐它
>>> variable = 23
>>> return_value = -5 if variable<-100 else -4 if variable<=-4 else 18 if variable<= 5 else 88
>>> print(return_value)
88
请注意 88
是默认值。
编辑
您可以创建一个基于与上述 if... else
相同概念的函数。该函数将是这样的:
def pythonic(variable, bucket_values, default):
for k,v in bucket_values:
return_value = v if variable<k else "---"
if return_value != "---":
return return_value
return default
你可以这样使用它:
>>> variable = 23
>>> bucket_values = [(-100, -15), (-5, -4), (5, 18)]
>>> print(pythonic(variable, bucket_values, 88))
88
>>> variable = 1
>>> print(pythonic(variable, bucket_values, 88))
18
如果我理解得很好,对于每个 "bucket" 你都有一个间隔。要检查值是否属于某个区间,您可以定义一个函数:
def check_value(value, interval):
if value in range(interval[0], interval[1]+1):
print('Value ', value)
print('Interval ', interval)
else:
pass
现在只需遍历间隔列表以查找值所属的位置:
for interval in list_of_intervals:
check_value(value, interval)
使用模块 operator
非常简单。这是一个例子:
>>> import operator
>>> bucket = (operator.ge, -100, operator.le, -5)
>>> def in_bucket(value, bucket): return bucket[0](value, bucket[1]) and bucket[2](value, bucket[3])
...
>>> in_bucket(-101, bucket)
False
>>> in_bucket(-100, bucket)
True
>>> in_bucket(-5, bucket)
True
>>> in_bucket(-4, bucket)
False
但是您可以通过定义更通用的结构来做得更好:
>>> conditions = ((operator.ge, -100), (operator.le, -5))
>>> def match_conditions(value, conditions): return all(c[0](value, c[1]) for c in conditions)
...
>>> match_conditions(-101, conditions)
False
>>> match_conditions(-100, conditions)
True
>>> match_conditions(-5, conditions)
True
>>> match_conditions(-4, conditions)
False
all
运算符 returns 为真当且仅当满足所有条件。 bucket
和 conditions
之间的主要区别在于您可以添加与边界无关的条件,例如值必须是对:
>>> conditions = ((operator.ge, -100), (operator.le, -5), (lambda v, _: v%2==0, None))
>>> match_conditions(-7, conditions)
False
>>> match_conditions(-6, conditions)
True
>>> match_conditions(-5, conditions)
False
现在你可以用字典来总结你的条件(你给的第一个例子):
>>> value_by_conditions = {
... ((operator.lt, -100),): -15,
... ((operator.ge, -100), (operator.le, -5)): -4,
... ((operator.gt, -5), (operator.le, 5)): 18,
... ((operator.gt, 5),): 88,
... }
>>> next((v for cs, v in value_by_conditions.items() if match_conditions(23, cs)), None)
88
>>> next((v for cs, v in value_by_conditions.items() if match_conditions(-101, cs)), None)
-15
>>> next((v for cs, v in value_by_conditions.items() if match_conditions(-100, cs)), None)
-4
备注:
- 我使用了元组,因为列表不可散列(因此不能用作字典键);
next((x for x in xs if <test>), None)
取xs
中第一个通过测试的元素。如果没有元素通过测试,它 returns 默认值None
;- 在旧版本的 Python (< 3.7) 中,您无法保证测试的顺序。如果您有重叠条件,这一点很重要。
- 这显然是次优的,因为你先测试 if
value < 100
然后 ifvalue >= 100
,等等
这真的是pythonic吗?我不确定。看看 https://www.python.org/dev/peps/pep-0020/ 来提出自己的想法。