PHP组合不同长度的多维数组

时间:2019-09-16 16:43:54

标签: php loops for-loop multidimensional-array merge

由于每个数组的长度未知,我需要重新排列以下多维数组以合并和填充索引。问题是,我不知道如果数组结构错误,将需要多少行或多少列。

我首先需要一个数组,其中包含字符串用户ID,研究ID,分离中的每个研究的问题,然后是日期。我不必担心这个数组,因为创建起来非常简单。

我遇到麻烦的地方是,每个User_Prediction需要一个数组,其中它们包含的长度与问题数量相同(这有意义吗?)。我最终要寻找的是创建一个CSV文件,该文件的标题由UserId,StudyId和所有问题的组合列表以及日期组成。因此,我可以采用下面的“所需输出”,并为每个数组fcsvput简单地说。如果我现在按照User_Predictions的原样使用,则在水平排列(例如CSV文件)时,它们不会与问题对齐。

这是一个示例数组:

[studies] => Array
(
    [0] => Array
        (
            [Study_ID] => 563
            [Questions] => Array
                (
                    [1] => S563 Q1
                    [2] => S563 Q2
                )
            [User_Predictions] => Array
                (
                    [0] => Array
                        (
                            [User_ID] => 24
                            [Answers] => Array
                                (
                                    [0] => 66
                                    [1] => Option 1
                                )
                        )
                )
        )

    [1] => Array
        (
            [Study_ID] => 510
            [Questions] => Array
                (
                    [1] => S510 Q1
                    [2] => S510 Q2
                    [3] => S510 Q3
                    [4] => S510 Q4
                    [5] => S510 Q5
                )

            [User_Predictions] => Array
                (
                    [0] => Array
                        (
                            [User_ID] => 76
                            [Answers] => Array
                                (
                                    [0] => 1
                                    [1] => 1
                                    [2] => Negative
                                    [3] => 10
                                    [4] => 2,2
                                )
                        )
                    [1] => Array
                        (
                            [User_ID] => 58
                            [Answers] => Array
                                (
                                    [0] => 25
                                    [1] => 20
                                    [2] => Positive
                                    [3] => 5000
                                    [4] => 1,2
                                )
                        )
                )
        )
)

这就是我要实现的目标:

Array
(
    [0] => User_ID
    [1] => Study_ID
    [2] => S563 Q1 
    [3] => S563 Q2 
    [4] => S510 Q1 
    [5] => S510 Q2 
    [6] => S510 Q3 
    [7] => S510 Q4 
    [8] => S510 Q5 
    [9] => Date
)


Array
(
    [0] => 24
    [1] => 563
    [2] => 66
    [3] => Option 1
    [4] => 
    [5] => 
    [6] => 
    [7] => 
    [8] => 
    [9] => Date
)


Array
(
    [0] => 76
    [1] => 510
    [2] => 
    [3] => 
    [4] => 1
    [5] => 1
    [6] => Negative
    [7] => 10
    [8] => 2,2
    [9] => Date
)   

Array
(
    [0] => 58
    [1] => 510
    [2] => 
    [3] => 
    [4] => 25
    [5] => 20
    [6] => Positive
    [7] => 5000
    [8] => 1,2
    [9] => Date
)

3 个答案:

答案 0 :(得分:3)

注意 :不确定date的来源。

首先,这是您的问题模式。

  • studies中的每个数组都有一个Study_ID和一组问题Questions和许多用户的用户谓词User_Predictions
  • 每个预测都有一个用户User_ID,并回答上一步中的问题。
  • index of question = index of answer + 1

您的问题:您希望每个用户预测都作为一个单独的数组,但如果该特定研究中存在问题,则应包括所有问题列表及其答案。

解决方案

为了进行预测,通常会有一个Study_ID和一个对此用户做出响应的用户User_ID

// This array will contain all indexes should be present in final array.
$arrIndex   =   ['Study_ID', 'User_ID'];      // Assume these two would always be present, so added in advance.

// This will be temporary array holds data for each user prediction with relevant information i.e. it would not have data for questions which are not in this study.
$arrUserStudy    =   [];

foreach($arr['studies'] as $arrStudy){

    foreach($arrStudy['Questions'] as $strQuestion){
        // To add a new question to the index.
        if(!in_array($strQuestion,  $arrIndex)){
            $arrIndex[] =   $strQuestion;
        }
    }

    foreach($arrStudy['User_Predictions'] as $userStudy){
        $arrTemp  =   [
            'Study_ID'  =>  $arrStudy['Study_ID'],
            'User_ID'   =>  $userStudy['User_ID'],
        ];

        foreach($userStudy['Answers'] as $intKey => $strAnswer){
            $arrTemp[$arrStudy['Questions'][$intKey + 1]]   =   $strAnswer;
        }
        $arrUserStudy[]     =    $arrTemp;
    }
}

输出:

print_r($arrIndex);

Array
(
    [0] => Study_ID
    [1] => User_ID
    [2] => S563 Q1
    [3] => S563 Q2
    [4] => S510 Q1
    [5] => S510 Q2
    [6] => S510 Q3
    [7] => S510 Q4
    [8] => S510 Q5
)


print_r($arrUserStudy);

Array
(
    [0] => Array
        (
            [Study_ID] => 563
            [User_ID] => 24
            [S563 Q1] => 66
            [S563 Q2] => Option 1
        )

    [1] => Array
        (
            [Study_ID] => 510
            [User_ID] => 76
            [S510 Q1] => 1
            [S510 Q2] => 1
            [S510 Q3] => Negative
            [S510 Q4] => 10
            [S510 Q5] => 2,2
        )

    [2] => Array
        (
            [Study_ID] => 510
            [User_ID] => 58
            [S510 Q1] => 25
            [S510 Q2] => 20
            [S510 Q3] => Positive
            [S510 Q4] => 5000
            [S510 Q5] => 1,2
        )

)

如果将此输出与您的输出进行比较,则只有以下差异:

  • 每个用户谓词都以key作为问题/ Study_Id / User_ID,但是在您的输出中,它是一个整数。
  • 它缺少其他研究的问题。

我们可以轻松地包含缺失的问题,因为我们确实在$arrIndex中包含了所有问题,而相应的值将是null

将字符串键更改为整数键:我更喜欢使用字符串键,因为即使它们没有顺序,您也可以使用其key_name轻松识别和访问它们。

最终转换为所需输出

保留字符串键并添加缺少的字符(首选):

foreach($arrUserStudy as $intKey =>  $userStudy){
    foreach($arrIndex as $strIndex){
        if(!array_key_exists($strIndex, $userStudy)){
            $arrUserStudy[$intKey][$strIndex] = null;
        }
    }
}

print_r($arrUserStudy);

Output:
Array
(
    [0] => Array
        (
            [Study_ID] => 563
            [User_ID] => 24
            [S563 Q1] => 66
            [S563 Q2] => Option 1
            [S510 Q1] => 
            [S510 Q2] => 
            [S510 Q3] => 
            [S510 Q4] => 
            [S510 Q5] => 
        )

    [1] => Array
        (
            [Study_ID] => 510
            [User_ID] => 76
            [S510 Q1] => 1
            [S510 Q2] => 1
            [S510 Q3] => Negative
            [S510 Q4] => 10
            [S510 Q5] => 2,2
            [S563 Q1] => 
            [S563 Q2] => 
        )

    [2] => Array
        (
            [Study_ID] => 510
            [User_ID] => 58
            [S510 Q1] => 25
            [S510 Q2] => 20
            [S510 Q3] => Positive
            [S510 Q4] => 5000
            [S510 Q5] => 1,2
            [S563 Q1] => 
            [S563 Q2] => 
        )

)

注意:这里您看到密钥没有排序,但是您可以循环$arrIndex并可以通过$arrUserStudy[<loop_variable>][<index_name>]在任意位置访问密钥。

转换为整数键并添加缺失的字符

$arrReindexed   =   [];
foreach($arrUserStudy as $intKey =>  $userStudy){
    $arrTemp    =   [];
    foreach($arrIndex as $intKey =>  $strIndex){
        $arrTemp[$intKey]   =   array_key_exists($strIndex, $userStudy) ?  $userStudy[$strIndex] : null;
    }

    $arrReindexed[]     =   $arrTemp;
}

print_r($arrReindexed);

Output:
Array
(
    [0] => Array
        (
            [0] => 563
            [1] => 24
            [2] => 66
            [3] => Option 1
            [4] => 
            [5] => 
            [6] => 
            [7] => 
            [8] => 
        )

    [1] => Array
        (
            [0] => 510
            [1] => 76
            [2] => 
            [3] => 
            [4] => 1
            [5] => 1
            [6] => Negative
            [7] => 10
            [8] => 2,2
        )

    [2] => Array
        (
            [0] => 510
            [1] => 58
            [2] => 
            [3] => 
            [4] => 25
            [5] => 20
            [6] => Positive
            [7] => 5000
            [8] => 1,2
        )

)

答案 1 :(得分:1)

这是获得所需结果的相对简单的解决方案。

本文的末尾有一些说明。

这是输入数据的数组:

$studiesData = Array
(
    "0" => Array
    (
        "Study_ID" => "563",
        "Questions" => Array
        (
            "1" => "S563 Q1",
            "2" => "S563 Q2"
        ),
        "User_Predictions" => Array
        (
            "0" => Array
            (
                "User_ID" => "24",
                "Answers" => Array
                (
                    "0" => "66",
                    "1" => "Option 1"
                )
            )
        )
    ),
    "1" => Array
    (
        "Study_ID" => "510",
        "Questions" => Array
        (
            "1" => "S510 Q1",
            "2" => "S510 Q2",
            "3" => "S510 Q3",
            "4" => "S510 Q4",
            "5" => "S510 Q5"
        ),
        "User_Predictions" => Array
        (
            "0" => Array
            (
                "User_ID" => "76",
                "Answers" => Array
                (
                    "0" => "1",
                    "1" => "1",
                    "2" => "Negative",
                    "3" => "10",
                    "4" => "2,2"
                )
            ),
            "1" => Array
            (
                "User_ID" => "58",
                "Answers" => Array
                (
                    "0" => "25",
                    "1" => "20",
                    "2" => "Positive",
                    "3" => "5000",
                    "4" => "1,2"
                )
            )
        )
    )
);

修复数组的索引以使用有序键将它们全部获取:

foreach ($studiesData as $k => &$studyData)
{
    $studyData['Questions'] = array_values($studyData['Questions']);
    foreach ($studyData['User_Predictions'] as $k2 => &$responses)
    {
        $responses['Answers'] = array_values($responses['Answers']);
    }
    unset($responses); // break the reference with the last element
}
unset($studyData); // break the reference with the last element

现在数组$studiesData是:

echo "<pre>";
print_r($studiesData);
echo "</pre>";

Array
(
    [0] => Array
        (
            [Study_ID] => 563
            [Questions] => Array
                (
                    [0] => S563 Q1
                    [1] => S563 Q2
                )

            [User_Predictions] => Array
                (
                    [0] => Array
                        (
                            [User_ID] => 24
                            [Answers] => Array
                                (
                                    [0] => 66
                                    [1] => Option 1
                                )
                        )
                )
        )

    [1] => Array
        (
            [Study_ID] => 510
            [Questions] => Array
                (
                    [0] => S510 Q1
                    [1] => S510 Q2
                    [2] => S510 Q3
                    [3] => S510 Q4
                    [4] => S510 Q5
                )

            [User_Predictions] => Array
                (
                    [0] => Array
                        (
                            [User_ID] => 76
                            [Answers] => Array
                                (
                                    [0] => 1
                                    [1] => 1
                                    [2] => Negative
                                    [3] => 10
                                    [4] => 2,2
                                )
                        )

                    [1] => Array
                        (
                            [User_ID] => 58
                            [Answers] => Array
                                (
                                    [0] => 25
                                    [1] => 20
                                    [2] => Positive
                                    [3] => 5000
                                    [4] => 1,2
                                )
                        )
                )
        )
)

将所有问题存储在专用数组中,为方便起见,我们将在以后使用它们:

$totalQuestions = array();
foreach ($studiesData as $k => $studyData)
{
    foreach ($studyData['User_Predictions'] as $responses)
    {
        foreach ($studyData['Questions'] as $questionDescription)
        {
            $totalQuestions[$questionDescription] = $questionDescription;
        }
    }
}

echo "<pre>";
print_r($totalQuestions);
echo "</pre>";

Array
(
    [S563 Q1] => S563 Q1
    [S563 Q2] => S563 Q2
    [S510 Q1] => S510 Q1
    [S510 Q2] => S510 Q2
    [S510 Q3] => S510 Q3
    [S510 Q4] => S510 Q4
    [S510 Q5] => S510 Q5
)

以所需的格式生成结果数组:

$result2 = array();
$result2[0][] = 'User_ID';
$result2[0][] = 'Study_ID';
$x = 1;
foreach($studiesData as $k => $studyData)
{
    foreach ($studyData['User_Predictions'] as $k2 => $userData)
    {
        $x++;
        $result2[$x][0] = $userData['User_ID'];
        $result2[$x][1] = $studyData['Study_ID'];

        foreach($totalQuestions as $questionDescription)
        {
            if(!in_array($questionDescription, $result2[0]))
            {
                $result2[0][] = $questionDescription;
            }

            if(($idQuestion = array_search($questionDescription, $studyData['Questions'])) !== false)
            {
                $result2[$x][] = $userData['Answers'][$idQuestion];
            }
            else
            {
                $result2[$x][] = '';
            }
        }
    }
}
echo "<pre>";
print_r($result2);
echo "</pre>";

最终输出

Array
(
    [0] => Array
        (
            [0] => User_ID
            [1] => Study_ID
            [2] => S563 Q1
            [3] => S563 Q2
            [4] => S510 Q1
            [5] => S510 Q2
            [6] => S510 Q3
            [7] => S510 Q4
            [8] => S510 Q5
        )

    [2] => Array
        (
            [0] => 24
            [1] => 563
            [2] => 66
            [3] => Option 1
            [4] => 
            [5] => 
            [6] => 
            [7] => 
            [8] => 
        )

    [3] => Array
        (
            [0] => 76
            [1] => 510
            [2] => 
            [3] => 
            [4] => 1
            [5] => 1
            [6] => Negative
            [7] => 10
            [8] => 2,2
        )

    [4] => Array
        (
            [0] => 58
            [1] => 510
            [2] => 
            [3] => 
            [4] => 25
            [5] => 20
            [6] => Positive
            [7] => 5000
            [8] => 1,2
        )
)

一些说明

  • array_values返回数组中的所有值,并对数组进行数字索引。

  • unset在foreach之后:如文档所述:

  

$ value的引用和最后一个数组元素即使在   foreach循环。建议通过unset()销毁它。

  • array_search在数组中搜索给定值,如果成功,则返回第一个对应的键。

需要对!==进行false检查,因为此函数可能返回布尔FALSE,但也可能返回非布尔值,其值为FALSE。

Date :问题的最终输出中有Date条目,但数组输入中没有。如果您更新了问题,我会在答案中包含它。

答案 2 :(得分:0)

我已尝试将其削减,以使步骤尽可能少。

这将其分为两个阶段,收集数据,然后格式化输出。我已在代码中添加了注释,因为它有助于在代码上下文中解释事物...

$entries = [];
$fields = ['User_ID' => null, 'Study_ID' => null];
// Input array of values is $data
foreach ( $data as $study ) {
    $studyOptions = [];
    foreach ( $study["Questions"] as $question )    {
        // Add questions to list of possibilities
        $fields[$question] = null;
        // Keep a list of the options for this question
        $studyOptions[] = $question;
    }
    foreach ( $study["User_Predictions"] as $prediction )   {
        $userData = ["User_ID" => $prediction["User_ID"],
            "Study_ID" => $study["Study_ID"]];
        // For each prediction, use the corresponding $studyOptions entry to set a field
        // with the prediction for this question
        foreach ( $prediction["Answers"] as $key => $value )   {
            $userData[$studyOptions[$key]] = $value;
        }
        // Add this to the list of data so far
        $entries[] = $userData;
    }
}

要显示到目前为止的一些数据...

print_r($entries[0]);
// First row of data example
// Array
// (
//     [User_ID] => 24
//     [Study_ID] => 563
//     [S563 Q1] => 66
//     [S563 Q2] => Option 1
// )

print_r($fields);
// List of fields to be used in final output
// Array
// (
//     [User_ID] =>
//     [Study_ID] =>
//     [S563 Q1] =>
//     [S563 Q2] =>
//     [S510 Q1] =>
//     [S510 Q2] =>
//     [S510 Q3] =>
//     [S510 Q4] =>
//     [S510 Q5] =>
//     )

最终格式化输出

$output = [array_keys($fields)];
foreach ( $entries as $entry )   {
    // Use array_replace - to create an entry with all $fields values 
    // from the current entry, use array_values to remove keys
    $output[] = array_values(array_replace($fields, $entry));
}

给..

Array
(
    [0] => Array
        (
            [0] => User_ID
            [1] => Study_ID
            [2] => S563 Q1
            [3] => S563 Q2
            [4] => S510 Q1
            [5] => S510 Q2
            [6] => S510 Q3
            [7] => S510 Q4
            [8] => S510 Q5
        )

    [1] => Array
        (
            [0] => 24
            [1] => 563
            [2] => 66
            [3] => Option 1
            [4] => 
            [5] => 
            [6] => 
            [7] => 
            [8] => 
        )
....