2010-10-27 40 views
12

Tôi đã một mảng phản ánh tỷ lệ phần trăm giảm giá tùy thuộc vào số lượng các mục ra lệnh:Chọn giá trị gần nhất từ ​​một mảng phản ánh dãy

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

nghĩa là cho một hoặc hai mục, bạn không nhận được giảm giá; cho 3+ mục bạn nhận được 10%, cho 5 mục trở lên 20%, cho 10+ 35% v.v.

thanh lịch, một cách để nhận tỷ lệ phần trăm giảm giá chính xác cho một số mục tùy ý, giả sử 7?

Rõ ràng, điều này có thể được giải quyết bằng cách sử dụng một vòng lặp đơn giản: Đó không phải là những gì tôi đang tìm kiếm. Tôi quan tâm cho dù có một mảng lõi hoặc chức năng khác mà tôi không biết rằng có thể làm điều này thanh lịch hơn.

Tôi sẽ trao giải thưởng được chấp nhận với số tiền thưởng là 200, nhưng rõ ràng, tôi phải chờ 24 giờ cho đến khi tôi có thể làm điều đó. Câu hỏi được giải quyết.

+3

bạn biết điều đó là vô nghĩa để xin một lớp lót khi bạn không xác định dòng có độ dài tối đa;) – Gordon

+0

phím đang không ở trong một mô hình? Vì vậy, chúng tôi không thể thực hiện một chức năng – nerkn

+0

@Gordon: Trong trước khi mã sân golf. – BoltClock

Trả lời

16

Dưới đây là một số khác, một lần nữa không ngắn gọn.

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

Ý tưởng cơ bản là để có được chìa khóa cao nhất (max) mà nằm đâu đó giữa 0$items.

+0

+1 gọn gàng và thực tế –

+0

Tôi chấp nhận điều này vì nó hoạt động không phá hủy, là cách tiếp cận ngắn nhất và không cần hình cầu/đóng cửa. Cảm ơn! –

+0

+1 tương đối ngắn và chức năng – Thariama

1

Không có chức năng cốt lõi nào như vậy!

1

tốt nhất tôi có thể quản lý cho đến nay:

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

Sử dụng một chút những đứa khó chịu của đi ngang qua tham khảo, và dải tắt bất kỳ mục trong mảng $ giảm giá mà quan trọng là số lượng lớn hơn $ testValue ... Thật không may, nó vẫn để lại các mục có khóa thấp hơn, do đó, một mảng_pop() sẽ là cần thiết để có được giá trị chính xác. Lưu ý rằng nó chủ động làm giảm các mục trong mảng $ rebates gốc.

Có lẽ ai đó có thể tạo điều này để loại bỏ các mục nhập thấp hơn trong mảng.

Hiện không có 5.3.3 sẵn có, do đó không được kiểm tra bằng chức năng ẩn danh, nhưng hoạt động (nhiều khi hoạt động) khi sử dụng chức năng gọi lại chuẩn.

EDIT

xây dựng trên trước một lót của tôi, thêm một dòng thứ hai (vì vậy có lẽ không nên đếm):

$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)); 

Bây giờ kết quả trong mảng $ giảm giá chỉ chứa một đơn phần tử, là khóa điểm ngắt cao nhất từ ​​mảng $ rebates ban đầu là khóa thấp hơn $ testValue.

+0

+1 Cách tiếp cận thú vị! –

2

Điều này có thể hoạt động mà không thay đổi mảng giảm giá.

Nhưng mảng phải được xây dựng theo một cách khác để làm việc này

$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; 

testcase làm việc, chỉ cần thay đổi tính trong url

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

+0

Rất đẹp, cảm ơn bạn. Tôi chấp nhận phương pháp tiếp cận của @ salathe bởi vì nó ngắn hơn một chút và hoạt động mà không có toàn cầu/đóng cửa, nhưng điều này cũng sẽ hoạt động tốt. –

+0

Vì lý do, giải pháp của anh ấy thanh lịch hơn :-) –

5

Tôi nghĩ rằng các giải pháp một dòng trên không thực sự thanh lịch hoặc dễ đọc. Vậy tại sao không sử dụng một cái gì đó thực sự có thể được hiểu bởi một ai đó trong nháy mắt đầu tiên?

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

Điều này rõ ràng cần có một mảng được sắp xếp, nhưng ít nhất trong ví dụ của bạn này được đưa ra;)

Được rồi, tôi biết, bạn không muốn các giải pháp với các vòng lặp đơn giản. Nhưng những gì về điều này:

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

Vẫn khá đơn giản, nhưng ngắn hơn một chút. Chúng ta có thể làm ngắn hơn không?

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

Chúng tôi đã nhận được gần một dòng. Vì vậy, hãy làm một chút gian lận:

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

Đây là ngắn hơn tất cả các phương pháp tiếp cận trong các câu trả lời khác. Nó chỉ có một bất lợi: Nó thay đổi giá trị của $items mà bạn vẫn có thể cần sau này. Vì vậy, chúng tôi có thể làm:

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

Lại một ký tự ít hơn và chúng tôi giữ $items.

Mặc dù tôi nghĩ rằng hai phiên bản cuối cùng đã quá hacky. Better gắn bó với thế này, vì nó là cả ngắn và dễ hiểu:

for ($i = $items; !isset($rabates[$i]); --$i); 
$rabate = $rabates[$i]; 
Các vấn đề liên quan