亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何通過交替“性別”值對關聯數組的數組進行排序?

如何通過交替“性別”值對關聯數組的數組進行排序?

PHP
一只甜甜圈 2021-11-26 19:42:28
我有一個數組數組:$students= array(    array("name"=>"...", "gender"=>"male"),    array("name"=>"...", "gender"=>"female"),    array("name"=>"...", "gender"=>"female"),    array("name"=>"...", "gender"=>"female"),    array("name"=>"...", "gender"=>"male"),    array("name"=>"...", "gender"=>"male"),    array("name"=>"...", "gender"=>"male"),);我想$students通過交替性別對元素進行排序以獲得:$students= array(    array("name"=>"...", "gender"=>"male"),    array("name"=>"...", "gender"=>"female"),    array("name"=>"...", "gender"=>"male"),    array("name"=>"...", "gender"=>"female"),    array("name"=>"...", "gender"=>"male"),    array("name"=>"...", "gender"=>"female"),    array("name"=>"...", "gender"=>"male"),);我怎樣才能做到這一點?
查看完整描述

3 回答

?
繁花不似錦

TA貢獻1851條經驗 獲得超4個贊

我通過將元素過濾到 2 個單獨的數組 ($males和$females)來做到這一點。array_filter保留鍵,所以我們只需將它傳遞array_values給從 0 開始的新鍵列表。從那里開始,這是一個簡單的 for 循環,將它們交織在一起并將它們添加到最終數組中。


<?php


$students= [

    ["name"=>"...", "gender"=>"male"],

    ["name"=>"...", "gender"=>"female"],

    ["name"=>"...", "gender"=>"female"],

    ["name"=>"...", "gender"=>"female"],

    ["name"=>"...", "gender"=>"male"],

    ["name"=>"...", "gender"=>"male"],

    ["name"=>"...", "gender"=>"male"],

];


$males = array_values(array_filter($students, function($s) { return $s["gender"] === "male"; }));

$females = array_values(array_filter($students, function($s) { return $s["gender"] === "female"; }));


$final = [];

$max = max(count($females), count($males));


for ($i=0; $i<$max; $i++) {

    if (isset($males[$i])) {

        $final[] = $males[$i];

    }


    if (isset($females[$i])) {

        $final[] = $females[$i];

    }

}


print_r($final);


查看完整回答
反對 回復 2021-11-26
?
慕運維8079593

TA貢獻1876條經驗 獲得超5個贊

天真的解決方案

您可以使用array_filter根據性別創建兩個組。然后使用將組壓縮成對array_map并運行對array_reduce以壓平結構:


$males = array_filter($students, function ($e) {

    return $e["gender"] === "male";

});

$females = array_filter($students, function ($e) {

    return $e["gender"] === "female";

});

$zipped = array_map(null, $males, $females);

$result = array_reduce($zipped, function ($a, $e) {

    if ($e[0]) $a[] = $e[0];

    if ($e[1]) $a[] = $e[1];

    return $a;  

}, []);

時間復雜度為 O(n)。


減少開銷

如果第一個解決方案的開銷太大,請考慮消除函數調用。它仍然是 O(n) 兩次傳遞,但分支預測應該處理合并循環中性別之間存在廣泛數量不平衡的情況:


foreach ($students as $student) {

    if ($student["gender"] === "male") {

        $males[]= $student;

    }

    else {

        $females[]= $student;

    }

}


$male_count = count($males);

$female_count = count($females);


for ($i = 0, $j = 0; $i < $male_count || $j < $female_count;) {

    if ($i < count($males)) {

        $result[]= $males[$i++];

    }


    if ($j < count($females)) {

        $result[]= $females[$j++];

    }

}

概括

上面的代碼假設兩件事:(1)"male"即使它產生次優交錯(根據OP 的規范)也應該始終是第一個;(2)只"gender"存在兩個值。


第一個問題可以通過修改上面的代碼片段在壓縮階段交換數組順序以優先選擇最長的數組來解決。


可以使用array_reduce為目標鍵的每個唯一值創建數組元素的分組來解決第二個問題,然后刪除硬編碼值以支持對這些按頻率降序排序的組進行迭代(可以添加打破平局的邏輯)。


以下代碼的時間復雜度為 O(n + k*log(k)),其中k是唯一值的數量。最壞的情況是,所有條目都是完全或幾乎唯一的,在這種情況下,由于多余的排序,我們有一個 O(n log(n)) 解決方案,但如果k是常數,則為 O(n) ,就像在 OP 的情況下一樣。


請注意,PHP 排序例程不穩定,因此您需要將數組打包和解壓縮為索引/元素對,或者使用索引以外的自定義打破平局策略。


<?php


function interleave_values($arr, $key) {

    $unique_values = array_unique(array_column($arr, $key));

    $buckets = array_reduce($arr, function ($a, $e) use ($key) {

        $a[$e[$key]][] = $e;

        return $a;

    }, []);

    rsort($buckets);

    $zipped = array_map(null, ...$buckets);

    return array_reduce($zipped, function ($a, $e) {

        foreach ($e as $f) {

            if (!$f) break;


            $a[] = $f;

        }


        return $a;  

    }, []);

}


$test = [

    ["k" => 1],

    ["k" => 2],

    ["k" => 1],

    ["k" => 3],

    ["k" => 3],

    ["k" => 1],

    ["k" => 2],

    ["k" => 2],

    ["k" => 2],

];

var_export(interleave_values($test, "k"));

輸出:


array (

  0 => 

  array (

    'k' => 2,

  ),

  1 => 

  array (

    'k' => 1,

  ),

  2 => 

  array (

    'k' => 3,

  ),

  3 => 

  array (

    'k' => 2,

  ),

  4 => 

  array (

    'k' => 1,

  ),

  5 => 

  array (

    'k' => 3,

  ),

  6 => 

  array (

    'k' => 2,

  ),

  7 => 

  array (

    'k' => 1,

  ),

  8 => 

  array (

    'k' => 2,

  ),

)



查看完整回答
反對 回復 2021-11-26
?
胡子哥哥

TA貢獻1825條經驗 獲得超6個贊

我不認為我建議創建臨時的特定于性別的數組,然后將它們拉鏈合并。


我喜歡維護兩個特定于性別的計數器并且只在一個循環中迭代它們的效率。我的循環不進行內部函數調用。


事實上,確定哪個性別應該先出現需要比新的關鍵分配更多的處理。


代碼:


$students = [

    ["name" => "...", "gender" => "male"],

    ["name" => "...", "gender" => "female"],

    ["name" => "...", "gender" => "female"],

    ["name" => "...", "gender" => "female"],

    ["name" => "...", "gender" => "male"],

    ["name" => "...", "gender" => "male"],

    ["name" => "...", "gender" => "male"],

];


$counters = ['female' => 1, 'male' => 1];


// determine which gender should start from 0

$genderCounts = array_count_values(

    array_column($students, 'gender')

);

arsort($genderCounts);

--$counters[key($genderCounts)];


// assign keys

$result = [];

foreach ($students as $student) {

    $gender = $student['gender'];

    $result[$counters[$gender]] = $student;

    $counters[$gender] += 2;

}


ksort($result);


var_export($result);


查看完整回答
反對 回復 2021-11-26
  • 3 回答
  • 0 關注
  • 190 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號