PHP выравнивание нескольких массивов разной длины

Я, вероятно, просто упускаю из виду очевидное, но я хотел бы обвинить в этом тот факт, что я новичок в PHP.

У меня есть некоторое количество массивов, которые возвращаются с похожей информацией, но разной ее суммой.

Я приведу несколько примеров массивов ниже:

(t1-s1-1=1, t1-s1-2=1, t1-s2-1=1, t1-s2-2=1)

(t2-s1-1=1, t2-s2-1=2, t2-s2-2=1)

(t3-s1-1=1, t3-s2-1=1, t3-s3-1=1, t3-s3-2=3)

Поэтому я хотел бы составить таблицу из этой информации. Что-то вроде этого:

test ..  s1-1 ..  s1-2 ..  s2-1 ..  s2-2 ..  s3-1 ..  s3-2
t1  ........1 .....1  ..........1 ....... 1.........1..........1
t2  ........1 .......X..........1..........1........1..........1
t3  ........1 .......X..........1..........X........1..........1

(где х — это то, чего там не было.)

Таким образом, каждый массив имеет s1 но мог бы иметь s1-1, s1-2, s1-3 или просто s1-1, Это создает массивы очень разных размеров.

Проблема в том, что каждый массив может иметь совершенно разную информацию, и поскольку они являются индексированными массивами, а не ассоциативными массивами, я не уверен, как лучше их выровнять. Я не могу последовательно сказать, что индекс 3 s1-3 или что-то другое.

Я не могу просто перебрать вручную, потому что никогда не знаю, где появится пробел. Я не могу искать конкретные индексы, потому что массивы не являются ассоциативными, поэтому заголовки встроены в значение, и я не знаю, как получить к ним доступ отдельно.

Есть хорошие идеи, которые, возможно, пропускает новичок? Я открыт для не табличных идей отображения, а также пока я могу легко сортировать и отображать информацию.

Спасибо

1

Решение

Я предполагаю, что ваши исходные массивы содержат значения в виде строки, поэтому, например, в синтаксисе PHP они выглядят так:

['t1-s1-1=1', 't1-s1-2=1', 't1-s2-1=1', 't1-s2-2=1']

По сути, вы должны создать двумерный массив:

  • пройти через все массивы и с помощью регулярных выражений извлечь различные части, то есть для первого элемента в массиве выше: t1 (индекс для первого уровня в двумерном массиве), s1-1 (индекс для второго уровня в двумерном массиве) и значение 1
  • вставить значение в двумерный массив
  • держать в отдельном массиве, давайте назовем его allColumns каждый второй индекс выше (sx-y), даже если у вас будут повторяющиеся значения, вы можете в конце удалить их и упорядочить по алфавиту

После этого у вас будет все значение в двумерном массиве, но вы все равно пропустите пробелы, поэтому вы можете выполнить итерацию по двумерному массиву и для каждого измерения tz (t1, t2, …), пройти через все значения, хранящиеся в allColumns и если вы не найдете запись для этого sx-y в двумерном массиве для этого tz, добавьте это значение x (или, возможно, со значением = 0)

Я думаю, что пример может прояснить выше:

// arrays of arrays, I don't know how you receive the data
$arrays = [
['t1-s1-1=1', 't1-s1-2=1', 't1-s2-1=1', 't1-s2-2=1'],
['t2-s1-1=1', 't2-s2-1=2', 't2-s2-2=1'],
['t3-s1-1=1', 't3-s2-1=1', 't3-s3-1=1', 't3-s3-2=3']
];

// bi-dimensional array
$output = [];

// it will store all columns you find in the $arrays entry
$allColumns = [];

// iterate for every array you receive, i.e. ['t1-s1-1=1', 't1-s1-2=1', 't1-s2-1=1', 't1-s2-2=1']
foreach ($arrays as $array) {
// iterate over every element in the array: 't1-s1-1=1', 't1-s1-2=1', 't1-s2-1=1' and 't1-s2-2=1'
foreach ($array as $item) {
// extract the parts on every element: $matches is an array containing the different parts
preg_match('/^(t\d+)-(s\d+-\d+)=(\d+)/', $item, $matches);
/**
* $matches[0] would contains the element if matched: 't1-s1-1=1'
* $matches[1] would contains 't1' if matched
* $matches[2] would contains 's1-1' if matched
* $matches[2] would contains 1 (integer) if matched
*/
if (!empty($matches)) {
$output[$matches[1]][$matches[2]] = $matches[3];
$allColumns[] = $matches[2];
}
}
}

// clean duplicates
$allColumns = array_unique($allColumns);

// sort values alphabetically
sort($allColumns);

// iterate over the just created bi-dimensional array
foreach ($output as $row => $columns) {
// iterate for all columns collected before
foreach ($allColumns as $column) {
// if one of column in 'allColumns' doesn't exit in $output you added in the correct place adding a zero value
if (!in_array($column, array_keys($columns))) {
$output[$row][$column] = 0;
}
}
}

Чтобы напечатать вывод, вам нужно только перебрать $ouput

Это будет массив внутри:

(
[t1] => Array
(
[s1-1] => 1
[s1-2] => 1
[s2-1] => 1
[s2-2] => 1
[s3-1] => 0
[s3-2] => 0
)

[t2] => Array
(
[s1-1] => 1
[s2-1] => 2
[s2-2] => 1
[s1-2] => 0
[s3-1] => 0
[s3-2] => 0
)

[t3] => Array
(
[s1-1] => 1
[s2-1] => 1
[s3-1] => 1
[s3-2] => 3
[s1-2] => 0
[s2-2] => 0
)

)

Существуют другие способы реализации вышеперечисленного, например, пропустить шаг, где вы заполняете пробелы и делаете это на лету, …

обновленный
Самый простой способ отобразить результаты на странице HTML — это встроить скрипт php для итерации по ассоциативному массиву и составить таблицу HTML (я рекомендую вам изучить и исследовать MVC, чтобы отделить логику от представления)

<!DOCTYPE html>
<?php
// arrays of arrays, I don't know how you receive the data
$arrays = [
['t1-s1-1=1', 't1-s1-2=1', 't1-s2-1=1', 't1-s2-2=1'],
['t2-s1-1=1', 't2-s2-1=2', 't2-s2-2=1'],
['t3-s1-1=1', 't3-s2-1=1', 't3-s3-1=1', 't3-s3-2=3']
];

// bi-dimensional array
$output = [];

// it will store all columns you find in the $arrays entry
$allColumns = [];

// iterate for every array you receive, i.e. ['t1-s1-1=1', 't1-s1-2=1', 't1-s2-1=1', 't1-s2-2=1']
foreach ($arrays as $array) {
// iterate over every element in the array: 't1-s1-1=1', 't1-s1-2=1', 't1-s2-1=1' and 't1-s2-2=1'
foreach ($array as $item) {
// extract the parts on every element: $matches is an array containing the different parts
preg_match('/^(t\d+)-(s\d+-\d+)=(\d+)/', $item, $matches);
/**
* $matches[0] would contains the element if matched: 't1-s1-1=1'
* $matches[1] would contains 't1' if matched
* $matches[2] would contains 's1-1' if matched
* $matches[2] would contains 1 (integer) if matched
*/
if (!empty($matches)) {
$output[$matches[1]][$matches[2]] = $matches[3];
$allColumns[] = $matches[2];
}
}
}

// clean duplicates
$allColumns = array_unique($allColumns);

// sort values alphabetically
sort($allColumns);

// iterate over the just created bi-dimensional array
foreach ($output as $row => $columns) {
// iterate for all columns collected before
foreach ($allColumns as $column) {
// if one of column in 'allColumns' doesn't exit in $output you added in the correct place adding a zero value
if (!in_array($column, array_keys($columns))) {
$output[$row][$column] = 0;
}
}
}
?>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Table Page</title>
</head>
<body>

<table>
<thead>
<?php
echo '<tr><th>Test</th>';
foreach ($allColumns as $head) {
echo sprintf('<th>%s</th>', $head);
}
echo '</tr>';
?>
</thead>
<tbody>
<?php
foreach ($output as $key => $columns) {
echo sprintf('<tr><td>%s</td>', $key);
foreach ($columns as $column) {
echo sprintf('<td>%s</td>', $column);
}
echo '</tr>';
}
?>

</tbody>
</table>
</body>
</html>
0

Другие решения

Попробуйте следующее:

$final_array = array();
$temp_array = array();
foreach ($t1 as $t) {
$isin = 0;
$expression = substr($t, 0, strpos($t, "="));
$expression = str_replace("t1-", "" , $expression)
$value = substr($t, strpos($t, "=") + 1);
for ($i = 0; $i < 3; $i++) {
foreach ($x = 0; $x < 3; $x++) {
if ($expression == "s{$i}-{$x}") {
$isin = 1;
array_push($temp_array, $value);
}
}
}
if ($isin == 0) { array_push($temp_array, "X"); }
}
array_push($final_array, $temp_array);

Это не очень хорошее решение, потому что вы решили сделать это действительно странным образом, но вы должны увидеть суть того, как получить то, что вы хотите из этого примера.

0