簡體   English   中英

如何按PHP中的特定列對列的多維數組進行排序?

[英]How to sort a multidimensional array of columns by a specific column in PHP?

我在PHP文檔中發現了用於對數組“列”進行排序的函數“ array_multisort”。 他們提供了一個示例,其中用戶具有一個行數組,然后用戶必須將該行數組轉換為列數組。 在我的情況下,數組已經由列設置,例如:

tablearray 

{

['Employee_ID'] = {0 => row1, 1 => row2, 2 => row3, 3 => row4}

['First_Name'] = {0 => row1, 1 => row2, 2 => row3, 3 => row4}

['LastName'] = {0 => row1, 1 => row2, 2 => row3, 3 =>row4}

 }

我想按Employee_ID排序,我需要所有其他列遵循相同的順序。 我試過了:

   array_multisort($tablearray['Employee_ID'], SORT_ASC);

但是,它僅對第一列進行排序(變成一團糟)。 該數組有10多個列,它根據搜索更改列名稱(列名稱是其鍵)。 在PHP的此函數的文檔中,提供的示例顯示,在將rows數組轉換為columns數組之后,我們應該使用原始數組作為與鍵匹配的第三個參數-我沒有“ original”數組要做比賽,因為我沒有改變任何東西。

謝謝。


一位用戶建議的所需輸出:

Original:

array
{

['Employee_ID'] = (1002, 4508, 0002, 1112)
['Business_Unit'] = ('UER', 'ABC', 'XYZ', 'EER')
['LastName'] = ('Smith', 'Vicente', 'Simpson', 'Thompson')

}

Sorted by Employee ID:

array
{

['Employee_ID'] = (0002, 1002, 1112, 4508)
['Business_Unit'] = ('XYZ', 'UER', 'EER', 'ABC')
['LastName'] = ('Simpson','Smith', 'Thompson', 'Vicente')

}

-我的原始數組是數據庫查詢輸出:

Array
 (
[0] => Array
    (
        [Employee_ID] => 0000
        [Supervisor_ID] => 00000
        [Location_Descr] => somewhere
        [Start_Date] => 06/03/2002
        [Service_Date] => 06/03/2002
        [Rehire_Date] => 00/00/00
        [Business_Unit] => YYYY
        [Job_Title] => Manager
        [Email] => email@example.com
        [Dept_Desc] => bla bla bla
        [Employee_Name_LF] => Last, First
        [Supervisor_Name_LF] => Last, First
        [Term_Date] => 00/00/00
        [Preferred_Name] => Someone
        [Source] => Sheet2
    )
)

還有幾行。 主要目的是將結果顯示為HTML表格並生成CSV文件。 我已經使用修改后的結構(我發布的第一個)進行了這些功能。 我認為處理這種結構會更容易...的確如此,但不幸的是並非如此。

array_multisort文檔( http://php.net/manual/en/function.array-multisort.php )建議將每一列分隔為一個單獨的數組。但是,如您所見,我有幾列(用戶可以選擇或多或少要在執行查詢之前顯示。。因此,我不能只在語句中列出所有它們)。

我願意更改所有內容,只是為了更好地使用代碼。

丑陋-如果格式化輸入表會容易得多。

$arr = array(
  'Employee_ID' => array('1002', '4508', '0002', '1112'),
  'Business_Unit' => array('UER', 'ABC', 'XYZ', 'EER'),
  'LastName' => array('Smith', 'Vicente', 'Simpson', 'Thompson')
);
$employees = array();
foreach (range(0, sizeof($arr[current(array_keys($arr))]) - 1) as $k) {
  $emp = array();
  foreach ($arr as $col => $vals) {
    $emp[$col] = $arr[$col][$k];
  }
  $employees[] = $emp;
}
$sort = array();
foreach ($employees as $k => $v) {
  $sort[$k] = $v['Employee_ID'];
}
array_multisort($sort, SORT_ASC, $employees);
print_r($employees);

並放回原始格式:

$arr_sorted = array();
foreach (array_keys($arr) as $col) {
  $arr_sorted[$col] = array();
  foreach ($employees as $emp) {
    $arr_sorted[$col][] = $emp[$col];
  }
}
print_r($arr_sorted);

感謝您發布問題中的其他詳細信息,因為它們確實有助於您理解問題的意圖。
現在,您沒有告訴我們該桌子的外觀; 如果您希望員工每行一位,或每列一位。 要知道哪種至關重要。 通常,每條生產線只有一名員工,特別是如果要將其導出到CVS。 但是,我懷疑是您想要的后者。 否則,您將以過於復雜的方式進行處理。

以防萬一:正常的單行布局:

<?php
$db = new PDO();

// Defining the fields we need here, to avoid having too long a string for the query.
$fields = "e.employee_id, e.first_name, e.lastname, u.business_unit, s.email";

// Do the sorting in the database itself. Not only is this faster, but it
// is also a lot easier to sort it exactly as you'd like.
// Note that I don't use prepared statements here, as there is no user-input.
$query = <<<outSQL
SELECT {$Fields} FROM `unit` AS u
INNER JOIN `employee` AS e ON e.employee_id = u.unit_id
INNER JOIN `employee` AS s ON s.employee_id = u.supervisor_id
ORDER BY e.`employee_id`
outSQL;

$data = $db->query($query);

// Creating a printf() template for the output, to make the code easier to maintain.
$rowTemplate = <<<outHTML
        <tr>
            <td>%1\$d</td>
            <td>%2\$s</td>
            <td>%3\$s</td>
        </tr>

outHTML;

// Generate the table template, using placeholders for where the data will be added..
$tableTemplate = <<<outHTML
<table>
    <thead>
        <tr>
            <th>ID</th>
            <th>First name</th>
            <th>Last name</th>
        </tr>
    </thead>
    <tbody>
%s
    </tbody>
</table>
outHTML;

// Regular table output, one employee per line.
$temp = '';
foreach ($data as $e) {
    // hs() is a shortcut function to htmlspecialchars (), to prevent against XSS.
    $temp .= sprintf($rowTemplate, $e['employee_id'], hs($e['first_name']), hs($e['lastname']));
}

// Add the rows to the table, so that you can echo the completed product wherever you need.
$employeeTable = sprintf($tableTemplate, $temp);

如果您想每列執行一次,則它會變得更加復雜。 雖然,仍然比您的第一次嘗試容易一些。 :)
即是這樣的:

<?php
$db = new PDO();

// Defining the fields we need here, to avoid having too long a string for the query.
$fields = "employee_id, first_name, lastname";

// Do the sorting in the database itself. Not only is this faster, but it
// is also a lot easier to sort it exactly as you'd like.
// Note that I don't use prepared statements here, as there is no user-input.
$data = $db->query("SELECT {$Fields} FROM `employees` ORDER BY `employee_id`");

// We need to know how many columns we'll have. One per employee.
$columns = count ($data);

// Rows have a header in front of each line, and one td tag for each employee.
$rowTemplate = "\t\t<th>%s</th>\n".str_repeat("\t\t\t<td>%s</td>\n", $columns);

// Generate the table template, using placeholders for where the data will be added..
$tableTemplate = <<<outHTML
<table>
    <tbody>
%s
    </tbody>
</table>
outHTML;

// Reformat the array to give us the data per-column.
$temp = array ();
foreach ($data as $field => $e) {
    // Since we've already sorted the data in the database we don't need to do any further sorting here.
    // Also note that I'm doing the escaping here, seeing as this array will only be used for output.
    $temp['Employee ID'][] = intval($e['employee_id']);
    $temp['First name'][] = hs($e['first_name']);
    $temp['Last name'][] = hs($e['lastname']);
}

// Now we do the same as in the above example.
$rows = '';
foreach ($temp as $label => $l) {
    // We have the label as the first template variable to be added, so put it as the first element.
    array_unshift($l, $label);

    // Add the current row of items to the output, using the previously established template.
    $rows = vprintf($rowTemplate, $l);
}

// Add the rows to the table, so that you can echo the completed product wherever you need.
$employeeTable = sprintf($tableTemplate, $temp);

PS:尚未測試代碼,但應該可以。

我遇到了他的問題,並且在許多煩惱之后,在php手冊頁的注釋中找到了一個非常不錯的解決方案-我現在有以下功能,可以在需要解決此類問題時使用。

function fnArrayOrderby(){
//function to sort a database type array of rows by the values in one or more column
//source http://php.net/manual/en/function.array-multisort.php - user notes
//example of use -> $sorted = fnArrayOrderby($data, 'volume', SORT_DESC, 'edition', SORT_ASC);

$args = func_get_args(); //Gets an array of the function's argument list (which can vary in length)
//echo "sorting  ".$args[0]."<br>";
if (!isset($args[0])) { return;}
$data = array_shift($args); //Shift an element off the beginning of array
foreach ($args as $n => $field) {
if (is_string($field)) {
$tmp = array();
foreach ($data as $key => $row)
$tmp[$key] = $row[$field];
$args[$n] = $tmp;
}
}
$args[] = &$data;
call_user_func_array('array_multisort', $args);
return array_pop($args);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM