繁体   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