简体   繁体   English

用3个索引PHP分组多维数组

[英]Group multidimentional array with 3 index PHP

I am not sure if I can explain this correctly but i will try, 我不确定我能否正确解释这一点,但我会尽力而为,

I have a multidimensional array which looks like the array below. 我有一个多维数组,看起来像下面的数组。 Notice changes in GROUPINDEX , ELOCATRIND and UNITINDEX . 注意GROUPINDEXELOCATRINDUNITINDEX中的更改 I tried a lot of looping, merge and filtering but couldn't able to achieve the desired result. 我尝试了很多循环,合并和过滤,但无法获得所需的结果。

Array
(
[0] => Array
    (
        [GROUPINDEX] => 1
        [GROUPDESC] => Grading Parameters
        [UNITINDEX] => 1
        [ELOCATRIND] => 1
        [ELOCATRDES] => Grading Date
        [ELOCATRVAL] => 123
        [CODEDESC] => 
    )

[1] => Array
    (
        [GROUPINDEX] => 1
        [GROUPDESC] => Grading Parameters
        [UNITINDEX] => 2
        [ELOCATRIND] => 1
        [ELOCATRDES] => Grading Decider
        [ELOCATRVAL] => abc
        [CODEDESC] => 
    )

[2] => Array
    (
        [GROUPINDEX] => 1
        [GROUPDESC] => Grading Parameters
        [UNITINDEX] => 5
        [ELOCATRIND] => 1
        [ELOCATRDES] => 
        [ELOCATRVAL] => test-DE
        [CODEDESC] => 
    )

[3] => Array
    (
        [GROUPINDEX] => 1
        [GROUPDESC] => Grading Parameters
        [UNITINDEX] => 1
        [ELOCATRIND] => 2
        [ELOCATRDES] => Grading Date
        [ELOCATRVAL] => 123-2
        [CODEDESC] => 
    )

[4] => Array
    (
        [GROUPINDEX] => 1
        [GROUPDESC] => Grading Parameters
        [UNITINDEX] => 2
        [ELOCATRIND] => 2
        [ELOCATRDES] => Grading Decider
        [ELOCATRVAL] => abc-2
        [CODEDESC] => 
    )

[5] => Array
    (
        [GROUPINDEX] => 2
        [GROUPDESC] => Genre Codes
        [UNITINDEX] => 1
        [ELOCATRIND] => 1
        [ELOCATRDES] => Grading Date
        [ELOCATRVAL] => 2017-02-01
        [CODEDESC] => 
    )

[6] => Array
    (
        [GROUPINDEX] => 2
        [GROUPDESC] => Genre Codes
        [UNITINDEX] => 2
        [ELOCATRIND] => 1
        [ELOCATRDES] => Grading Decider
        [ELOCATRVAL] => NGR
        [CODEDESC] => 
    )
)

I need to group them in hierarchical order according to the above mentioned indexes. 我需要根据上述索引按层次结构将它们分组。 the final result should look like this: 最终结果应如下所示:

Array
(
[0] => Array
    (
        [GROUPINDEX] => 1
        [GROUPDESC] => Grading Parameters
        [UNITINDEX] => 1
        [ELOCATRIND] => 1, 2
        [ELOCATRDES] => Grading Date:123 | Grading Date : 123-2

    )

[1] => Array
    (
        [GROUPINDEX] => 1
        [GROUPDESC] => Grading Parameters
        [UNITINDEX] => 2
        [ELOCATRIND] => 1, 2
        [ELOCATRDES] => Grading Decider:abc| Grading Decider:abc-2
    )

[2] => Array
    (
        [GROUPINDEX] => 1
        [GROUPDESC] => Grading Parameters
        [UNITINDEX] => 5
        [ELOCATRIND] => 1
        [ELOCATRDES] => 
        [ELOCATRVAL] => test-DE
        [CODEDESC] => 
    )


[5] => Array
    (
        [GROUPINDEX] => 2
        [GROUPDESC] => Genre Codes
        [UNITINDEX] => 1
        [ELOCATRIND] => 1
        [ELOCATRDES] => Grading Date
        [ELOCATRVAL] => 2017-02-01
        [CODEDESC] => 
    )

[6] => Array
    (
        [GROUPINDEX] => 2
        [GROUPDESC] => Genre Codes
        [UNITINDEX] => 2
        [ELOCATRIND] => 1
        [ELOCATRDES] => Grading Decider
        [ELOCATRVAL] => NGR
        [CODEDESC] => 
    )
)

I tried following snippet after some sanitization but it didn't work, and now I am out of ideas. 经过一些消毒后,我尝试按照以下代码段进行操作,但是它没有用,现在我没有主意了。

$result1 = array_map(
    function ($id) use ($Array) {
       return array_map(function ($data) {
            if (is_array($data)) return join(" | ", array_unique($data));
            return $data;
        }, array_reduce(
                array_filter($Array, function ($item) use ($id) { return $id === $item['UNITINDEX']; }),
                function ($result1, $set) { return $result1 = array_filter(array_merge_recursive($result1, $set)); }, [ ]
            )
        );
    },
    array_unique(array_column($Array, 'UNITINDEX'))
);

Any help would be great and really appreciated. 任何帮助将是巨大的,非常感谢。

You talk about 3 indexes, but you don't use them as indexes at all. 您谈论了3个索引,但根本没有将它们用作索引。 Let's use them; 让我们使用它们; how about having a result like this? 这样的结果怎么样?

First index is GROUPINDEX. 第一个索引是GROUPINDEX。

[1] => [
    [GROUPDESC] => Grading Parameters
    [UNITINDEX] => [
        [1] => [
            [ELOCATRIND] => 1, 2
            [ELOCATRDES] => Grading Date: 123 | Grading Date : 123-2
        ]
        [2] => [
            [ELOCATRIND] => 1, 2
            [ELOCATRDES] => Grading Decider: abc | Grading Decider: abc-2
        ]
        [5] => [
            [ELOCATRIND] => 1
            [ELOCATRDES] => 
        ]
    ]
]
[2] => [
        [GROUPDESC] => Genre Codes
        [UNITINDEX] => [
        [1] => [
            [ELOCATRIND] => 1
            [ELOCATRDES] => Grading Date: 2017-02-01
        ]
        [2] => [
            [ELOCATRIND] => 1
            [ELOCATRDES] => Grading Decider: NGR
        ]
    ]
]

The function to get that: 得到的功能:

<?php
function parseArr($arr) {
    $return = [];
    foreach($arr as $item) {
        // Check if GROUPINDEX exists
        if(!isset($return[$item['GROUPINDEX']]) {
            $return[$item['GROUPINDEX']] = [
                'GROUPDESC' => $item['GROUPDESC'],
                'UNITINDEX' => []
            ];
        }
        // Check if UNITINDEX exists in this GROUPINDEX
        if(!isset($return[$item['GROUPINDEX']]['UNITINDEX'][$item['UNITINDEX']])) {
            // Create UNITINDEX array
            $return[$item['GROUPINDEX']]['UNITINDEX'][$item['UNITINDEX']] = [
                'ELOCATRIND' => $item['ELOCATRIND'],
                'ELOCATRDES' => $item['ELOCATRDES'] . ': ' . $index['ELOCATRVAL']
            ];
        } else {
            // Update UNITINDEX array, just concat to previous values
            $return[$item['GROUPINDEX']]['UNITINDEX'][$item['UNITINDEX']]['ELOCATRIND'] .= ', ' . $item['ELOCATRIND'];
            $return[$item['GROUPINDEX']]['UNITINDEX'][$item['UNITINDEX']]['ELOCATRDES'] .= ' | ' . $item['ELOCATRDES'] . ': ' . $index['ELOCATRVAL'];
        }
    }
    return $return;
}

This should give you a start. 这应该给您一个开始。

<?php
$items = [
    [
        'GROUPINDEX' => 1,
        'GROUPDESC' => 'Grading Parameters',
        'UNITINDEX' => 1,
        'ELOCATRIND' => 1,
        'ELOCATRDES' => 'Grading Date',
        'ELOCATRVAL' => '123',
        'CODEDESC' => null
    ], [
        'GROUPINDEX' => 1,
        'GROUPDESC' => 'Grading Parameters',
        'UNITINDEX' => 2,
        'ELOCATRIND' => 1,
        'ELOCATRDES' => 'Grading Decider',
        'ELOCATRVAL' => 'abc',
        'CODEDESC' => null
    ], [
        'GROUPINDEX' => 1,
        'GROUPDESC' => 'Grading Parameters',
        'UNITINDEX' => 5,
        'ELOCATRIND' => 1,
        'ELOCATRDES' => null,
        'ELOCATRVAL' => 'test-DE',
        'CODEDESC' => null
    ], [
        'GROUPINDEX' => 1,
        'GROUPDESC' => 'Grading Parameters',
        'UNITINDEX' => 1,
        'ELOCATRIND' => 2,
        'ELOCATRDES' => 'Grading Date',
        'ELOCATRVAL' => '123-2',
        'CODEDESC' => null
    ], [
        'GROUPINDEX' => 1,
        'GROUPDESC' => 'Grading Parameters',
        'UNITINDEX' => 2,
        'ELOCATRIND' => 2,
        'ELOCATRDES' => 'Grading Decider',
        'ELOCATRVAL' => 'abc-2',
        'CODEDESC' => null
    ], [
        'GROUPINDEX' => 2,
        'GROUPDESC' => 'Genre Codes',
        'UNITINDEX' => 1,
        'ELOCATRIND' => 1,
        'ELOCATRDES' => 'Grading Date',
        'ELOCATRVAL' => '2017-02-01',
        'CODEDESC' => null
    ], [
        'GROUPINDEX' => 2,
        'GROUPDESC' => 'Genre Codes',
        'UNITINDEX' => 2,
        'ELOCATRIND' => 1,
        'ELOCATRDES' => 'Grading Decider',
        'ELOCATRVAL' => 'NGR',
        'CODEDESC' => null
    ]
];

// let create's a dictionary (associative array) keyed on the GROUPINDEX|UNITINDEX
$dict = [];

foreach ($items as $item) {
    $key = $item['GROUPINDEX'] . '|' . $item['UNITINDEX'];
    // check if key does not exist in the dictionary to create a new entry
    if (!isset($dict[$key])) {
        $dict[$key] = [
            'GROUPINDEX' => $item['GROUPINDEX'],
            'GROUPDESC' => $item['GROUPDESC'],
            'UNITINDEX' => $item['UNITINDEX'],
            // for convenience, we'll use arrays here
            'ELOCATRIND' => [],
            'ELOCATRDES' => []
        ];
    }
    // add item to dictionary's entry
    $dict[$key]['ELOCATRIND'][] = $item['ELOCATRIND'];

    // @TODO: ADD SOME CONDITIONAL LOGIC HERE

    $dict[$key]['ELOCATRDES'][] = $item['ELOCATRDES'] . ':' . $item['ELOCATRVAL'];
}

// let's clean up the dictionary now
foreach ($dict as $key => $item) {
    $dict[$key]['ELOCATRIND'] = implode(', ', $item['ELOCATRIND']);
    $dict[$key]['ELOCATRDES'] = implode(' | ', $item['ELOCATRDES']);
}

// sort dictionary by key
ksort($dict);
// remove keys
$dict = array_values($dict);

echo '<pre>' . print_r($dict, true) . '</pre>';
?>

It will output 它将输出

Array
(
    [0] => Array
        (
            [GROUPINDEX] => 1
            [GROUPDESC] => Grading Parameters
            [UNITINDEX] => 1
            [ELOCATRIND] => 1, 2
            [ELOCATRDES] => Grading Date:123 | Grading Date:123-2
        )

    [1] => Array
        (
            [GROUPINDEX] => 1
            [GROUPDESC] => Grading Parameters
            [UNITINDEX] => 2
            [ELOCATRIND] => 1, 2
            [ELOCATRDES] => Grading Decider:abc | Grading Decider:abc-2
        )

    [2] => Array
        (
            [GROUPINDEX] => 1
            [GROUPDESC] => Grading Parameters
            [UNITINDEX] => 5
            [ELOCATRIND] => 1
            [ELOCATRDES] => :test-DE  
        )

    [3] => Array
        (
            [GROUPINDEX] => 2
            [GROUPDESC] => Genre Codes
            [UNITINDEX] => 1
            [ELOCATRIND] => 1
            [ELOCATRDES] => Grading Date:2017-02-01
        )

    [4] => Array
        (
            [GROUPINDEX] => 2
            [GROUPDESC] => Genre Codes
            [UNITINDEX] => 2
            [ELOCATRIND] => 1
            [ELOCATRDES] => Grading Decider:NGR
        )

)

You'll notice the last three are not the same as your desired result. 您会注意到最后三个与您期望的结果不同。 You would have to add the logic where it says @TODO in comments (because I don't know). 您必须在注释@TODO表示的地方添加逻辑(因为我不知道)。

Your code attempts were very close. 您的代码尝试非常接近。 array_map() would be a good choice if the desired had one value corresponding to each element in the original array. 如果所需数组具有一个与原始数组中每个元素相对应的值,则array_map()将是一个不错的选择。 However, because the desired output doesn't have one element for each element in the original array, use array_reduce() with array_filter() inside instead of array_map() . 但是,由于所需的输出对于原始数组中的每个元素都没有一个元素,因此请在array_reduce()中使用array_filter()而不是array_map() That way, when using array_reduce(), the code can conditionally add the current item to the result array or update the existing item that has the matching UNITINDEX and GROUPINDEX values. 这样,当使用array_reduce()时,代码可以有条件地将当前项目添加到结果数组中,或更新具有匹配UNITINDEXGROUPINDEX值的现有项目。

In the code snippet below, also notice that array_keys() is used to get the index of the first found item (if it exists), and array_key_exists() is used to check if the key ELOCATRVAL exists on the found item. 在下面的代码片段中,还请注意, array_keys()用于获取找到的第一个项目的索引(如果存在),而array_key_exists()用于检查找到的项目上是否存在键ELOCATRVAL In that case, the value is appended to the ELOCATRDES key and the existing value is unset (using unset() ). 在这种情况下,该值将附加到ELOCATRDES键,并且未设置现有值(使用unset() )。

$result1 = array_reduce($Array, function($result, $currentItem) {
    $existingItems = array_filter($result, function ($item) use ($currentItem) { 
        return $currentItem['UNITINDEX'] === $item['UNITINDEX'] && $currentItem['GROUPINDEX'] === $item['GROUPINDEX']; 
    });
    if (count($existingItems)) {//matching item found
        $index = array_keys($existingItems)[0];
        if (array_key_exists('ELOCATRVAL', $result[$index])) {
            $result[$index]['ELOCATRDES'] .= ':'.$result[$index]['ELOCATRVAL'];
            unset($result[$index]['ELOCATRVAL']);
        }
        $result[$index]['ELOCATRIND'] .= ', '.$currentItem['ELOCATRIND'];
        $result[$index]['ELOCATRDES'] .= '| '.$currentItem['ELOCATRDES'].':'.$currentItem['ELOCATRVAL'];
    }
    else { //no match - push the item into the array
        $result[] = $currentItem;
    }
    return $result; //return cumulative array after iterating over each item 
}, []); //pass empty array as initial value of $result

See a demonstration of this in this PHP playground example . 此PHP游乐场示例中查看此演示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM