【问题标题】:Picking the nearest value from an array reflecting ranges从反映范围的数组中选择最近的值
【发布时间】:2010-10-27 11:33:23
【问题描述】:

我有一个数组,根据订购的商品数量反映返利百分比:

$rebates = array(
   1 => 0,
   3 => 10,
   5 => 25,
  10 => 35)

意思是一两件商品,你没有回扣;超过 3 件,你得到 10%,超过 5 件,20%,10+ 35%,依此类推。

是否有一种优雅的单行方式来获得任意数量项目的正确返利百分比,例如7

显然,这可以使用一个简单的循环来解决:这不是我想要的。我很感兴趣是否有一个我不知道的核心数组或其他函数可以更优雅地做到这一点。

我将奖励接受的答案 200,但显然,我必须等待 24 小时才能做到这一点。问题解决了。

【问题讨论】:

  • 没有这个核心功能!
  • 你知道当你没有指定最大行长时,要求单行是没有意义的;)
  • 键不在模式中?因此我们不能做一个函数
  • 我认为这应该是一个维基。
  • @evolve:如果你认为这应该是 CW,请标记为 mod 注意并告诉他们让它成为 CW。此外,我不明白为什么这应该是 CW ;)

标签: php arrays


【解决方案1】:

这是另一个,一点也不短。

$percent = $rebates[max(array_intersect(array_keys($rebates),range(0,$items)))];

这个想法基本上是获得最高的密钥 (max),它介于 0$items 之间。

【讨论】:

  • 我接受这个是因为它非破坏性地工作,是最短的方法,并且不需要全局/闭包。谢谢!
  • +1 我喜欢这个想法,但我永远不会在生产代码中使用它。
【解决方案2】:

我认为上述单行解决方案并不优雅或可读。那么为什么不使用别人一眼就能理解的东西呢?

$items = NUM_OF_ITEMS;
$rabate = 0;
foreach ($rabates as $rItems => $rRabate) {
    if ($rItems > $items) break;
    $rabate = $rRabate;
}

这显然需要一个排序数组,但至少在你的例子中这是给定的;)

好的,我知道,您不想要简单循环的解决方案。但是这个呢:

while (!isset($rabates[$items])) {
    --$items;
}
$rabate = $rabates[$items];

仍然很简单,但有点短。我们可以做得更短吗?

for (; !isset($rabates[$items]); --$items);
$rabate = $rabates[$items];

我们已经接近一条线了。所以让我们做一点作弊吧:

for (; !isset($rabates[$items]) || 0 > $rabate = $rabates[$items]; --$items);

这比其他答案中的所有方法都短。它只有一个缺点:它改变了$items 的值,您以后可能仍然需要它。所以我们可以这样做:

for ($i = $items; !isset($rabates[$i]) || 0 > $rabate = $rabates[$i]; --$i);

又少了一个字符,我们保留$items

虽然我认为最后两个版本已经太老套了。最好坚持这个,因为它既简短又易于理解:

for ($i = $items; !isset($rabates[$i]); --$i);
$rabate = $rabates[$i];

【讨论】:

    【解决方案3】:

    这可能会在不更改返利数组的情况下工作。

    但数组必须以另一种方式构造才能工作

    $rebates = array(
       3 => 0,      //Every number below this will get this rebate
       5 => 10,
       10 => 25,
      1000 => 35);  //Arbitrary large numer to catch all
    
    $count = $_REQUEST["count"];
    
    $rv = $rebates[array_shift(array_filter(array_keys($rebates), function ($v) {global $count; return $v > $count;}))];
    
    echo $rv;
    

    工作测试用例,只需更改 url 中的计数

    http://empirium.dnet.nu/arraytest.php?count=5
    http://empirium.dnet.nu/arraytest.php?count=10

    【讨论】:

    • 非常好,谢谢。我接受@salathe 的方法,因为它有点短,并且没有全局/闭包也可以工作,但这也可以正常工作。
    • 当然,他的解决方案更优雅:-)
    【解决方案4】:

    目前为止我能做到的最好的:

    $testValue = 7;
    array_walk( $rebates, function($value, $key, &$test) { if ($key > $test[0]) unset($test[1][$key]); } array($testValue,&$rebates) );
    

    使用了一个令人讨厌的按引用传递的小怪癖,并删除了 $rebates 数组中键在数值上大于 $testValue 的任何条目......不幸的是,它仍然留下低键条目,所以一个 array_pop()将需要获得正确的值。请注意,它会主动减少原始 $rebates 数组中的条目。

    也许有人可以在此基础上丢弃数组中较低的条目。

    目前手头没有可用的 5.3.3,因此未使用匿名函数进行测试,但在使用标准回调函数时可以正常工作(尽可能多地工作)。

    编辑

    在我之前的单行的基础上,添加第二行(所以可能不应该计算在内):

    $testValue = 7;
    array_walk( $rebates, function($value, $key, &$test) { if ($key > $test[0]) unset($test[1][$key]); } array($testValue,&$rebates) );
    array_walk( array_reverse($rebates,true), function($value, $key, &$test) { if ($key < $test[0]) unset($test[1][$key]); } array(array_pop(array_keys($rebates)),&$rebates) );
    

    现在 $rebates 数组只包含一个元素,它是原始 $rebates 数组中的最高断点键,它是低于 $testValue 的键。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-01-06
      • 1970-01-01
      • 1970-01-01
      • 2015-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多