0

データベースからのレコードの配列があります(データベースはこの質問とは無関係ですが、最終的には「行」の配列になり、各行はフィールド名に対応する文字列キーを持つ配列になります)。例えば:

$items = array(
    1 => array('id' => 1, 'name' => 'John', 'created' => '2011-08-14 8:47:39'),
    2 => array('id' => 2, 'name' => 'Mike', 'created' => '2011-08-30 16:00:12'),
    3 => array('id' => 5, 'name' => 'Jane', 'created' => '2011-09-12 2:30:00'),
    4 => array('id' => 7, 'name' => 'Mary', 'created' => '2011-09-14 1:18:40'),
    5 => array('id' => 16, 'name' => 'Steve', 'created' => '2011-09-14 3:10:30'),
    //etc...
);

私がやりたいのは、この配列をシャッフルすることですが、どういうわけか、より新しい「作成された」タイムスタンプを持つアイテムにより多くの「重み」を与えます。ランダム性は完全である必要はなく、正確な重みは私にとって実際には重要ではありません。言い換えれば、人間にはちょっとランダムに見えるが数学的にはランダムではない、速くて簡単なテクニックがあれば、私はそれで大丈夫です。また、タイムスタンプの「無限の連続体」でこれを行うのが簡単でない場合は、各レコードを1日または1週間に割り当て、それらがどの曜日または週にあるかに基づいて重み付けを行うのが適切です。 。

このランダム化は、私のWebサイトの特定のページが読み込まれるたびに発生するため、比較的高速で効率的な手法が望ましいです(ただし、効率的に実行できない場合は、定期的に実行して結果をキャッシュしてもかまいません)。

4

4 に答える 4

1

たとえば、を使用できます。この比較関数:

function cmp($a, $b){
    $share_of_a = $a['id'];
    $share_of_b = $b['id'];
    return rand(0, ($share_of_a+$share_of_b)) > $share_of_a ? 1 : -1;
}

次に、次のように使用します。

usort($items, 'cmp');

IDに基づいて配列の2つの要素を比較します(より簡単で、作成日に基づいて割り当てられます。新しい要素のIDは大きくなります)。比較はランダムに行われ、要素ごとに成功の可能性が異なり、新しい要素により多くの可能性が与えられます。IDが大きいほど(要素が新しいほど)、最初に表示される可能性が高くなります

たとえば、の要素id=16は、結果のリストの前に表示される要素の16倍の可能性があります。id=1

于 2011-11-13T04:39:27.043 に答える
0

それを日付ごとにチャンクに分割し、各チャンクをランダム化してから、それらを1つのリストとして元に戻すのはどうでしょうか。

于 2011-11-13T04:34:14.043 に答える
0
//$array is your array
$mother=array();
foreach($array as $k->$v) $mother[rand(0,count($array))][$k]=$v;
ksort($mother);
$child=array();
foreach($mother as $ak->$av)
foreach($av as $k->$v) $child[$k]=$v;
$array=$child;

または、shuffle()を使用できます

于 2011-11-13T04:37:02.370 に答える
0

@Tadeckからの応答に部分的に触発された後、私は解決策を思いつきました。誰かがそれを単純化することができれば、それは素晴らしいことです。しかし、それはうまく機能しているようです:

//Determine lowest and highest timestamps
$first_item = array_slice($items, 0, 1);
$first_item = $first_item[0];
$min_ts = strtotime($first_item['created']);
$max_ts = strtotime($first_item['created']);
foreach ($items as $item) {
    $ts = strtotime($item['created']);
    if ($ts < $min_ts) {
        $min_ts = $ts;
    }
    if ($ts > $max_ts) {
        $max_ts = $ts;
    }
}

//bring down the min/max to more reasonable numbers
$min_rand = 0;
$max_rand = $max_ts - $min_ts;

//Create an array of weighted random numbers for each item's timestamp
$weighted_randoms = array();
foreach ($items as $key => $item) {
    $random_value = mt_rand($min_rand, $max_rand); //use mt_rand for a higher max value (plain old rand() maxes out at 32,767)
    $ts = strtotime($item['created']);
    $ts = $ts - $min_ts; //bring this down just like we did with $min_rand and $max_rand
    $random_value = $random_value + $ts;
    $weighted_randoms[$key] = $random_value;
}

//Sort by our weighted random value (the array value), with highest first.
arsort($weighted_randoms, SORT_NUMERIC);

$randomized_items = array();
foreach ($weighted_randomsas $item_key => $val) {
    $randomized_items[$item_key] = $items[$item_key];
}

print_r($randomized_items);
于 2011-11-14T01:03:10.940 に答える