Форум программистов, компьютерный форум, киберфорум
PHP для начинающих
Войти
Регистрация
Восстановить пароль
 
0 / 0 / 0
Регистрация: 26.10.2011
Сообщений: 24
1

Отформатировать плоские и вложенные массивы

18.01.2021, 17:57. Просмотров 217. Ответов 1
Метки нет (Все метки)

Добрый день!

Есть пара вопросов, бьюсь над ними уже долгое время.

1) В общем есть код для сравнения двух файлов, json и yml, json и json, yml и yml.
Результат это различия в файлах, типа Было и Стало.
К тем данным которые добавились, перед ключом добавляем +, минус добавляем к тем которые были удалены, те что были неизменны оставляем без знаков, просто с отступом.

К примеру:
JSON
1
2
3
4
5
6
{
  "host": "site.com",
  "timeout": 50,
  "proxy": "123.234.53.22",
  "follow": false
}
сравниваем с:
JSON
1
2
3
4
5
{
  "timeout": 20,
  "verbose": true,
  "host": "site.com"
}
Собранные данные после сравнения эти двух файлов (промежуточный вариант перед форматированием):
Код
Array
(
    [0] => Array
        (
            [key] => host
            [value] => site.com
            [status] => not changed
        )

    [1] => Array
        (
            [key] => timeout
            [oldValue] => 50
            [newValue] => 20
            [status] => changed
        )

    [2] => Array
        (
            [key] => proxy
            [value] => 123.234.53.22
            [status] => removed
        )

    [3] => Array
        (
            [key] => follow
            [value] => 
            [status] => removed
        )

    [4] => Array
        (
            [key] => verbose
            [value] => 1
            [status] => added
        )

)
Применяем код для формирования строки в нужном виде (работает только для плоских данных):
Константа STARTTOSORTFROMSYMBOL = 4 , отвечает за то, что бы сортировать данные по первой букве по ключу, на 5 индексе начинается ключ, что бы просчитать отступы.
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
foreach ($data as $item) {
            if ($item['status'] === 'changed') {
                $tempResult[] = "  - " . $item['key'] . ': ' . var_export($item['oldValue'], true);
                $tempResult[] = "  + " . $item['key'] . ': ' . var_export($item['newValue'], true);
            }
            if ($item['status'] === 'not changed') {
                $tempResult[] = "    " . $item['key'] . ': ' . var_export($item['value'], true);
            }
            if ($item['status'] === 'added') {
                $tempResult[] = "  + " . $item['key'] . ': ' . var_export($item['value'], true);
            }
            if ($item['status'] === 'removed') {
                $tempResult[] = "  - " . $item['key'] . ': ' . var_export($item['value'], true);
            }
        }
        usort($tempResult, function ($a, $b) {
            return substr($a, STARTTOSORTFROMSYMBOL, 1) <=> substr($b, STARTTOSORTFROMSYMBOL, 1);
        });
        $tempResult = str_replace("'", '', $tempResult);
        $finalResult = "{" . "\n" . implode("\n", $tempResult) . "\n" . "}";

И финальный готовый вариант, то что мне и нужно было в нужном порядке:
Код
{
  - follow: false
    host: hexlet.io
  - proxy: 123.234.53.22
  - timeout: 50
  + timeout: 20
  + verbose: true
}
Помогите пожалуйста сделать тоже самое для вложенных данных?

К примеру сравниваем первый файл json:
JSON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
  "common": {
    "setting1": "Value 1",
    "setting2": 200,
    "setting3": true,
    "setting6": {
      "key": "value",
      "doge": {
        "wow": ""
      }
    }
  },
  "group1": {
    "baz": "bas",
    "foo": "bar",
    "nest": {
      "key": "value"
    }
  },
  "group2": {
    "abc": 12345,
    "deep": {
      "id": 45
    }
  }
}
Сравниваем со вторым файлом в формате YML:
Код
common:
  follow: false
  setting1: Value 1
  setting3: null
  setting4: blah blah
  setting5:
    key5: value5
  setting6:
    key: value
    ops: vops
    doge:
      wow: so much
group1:
  foo: bar
  baz: bars
  nest: str
group3:
  fee: 100500
  deep:
    id:
      number: 45

Мои уже собранные данные:
Код
Array
(
    [0] => Array
        (
            [key] => common
            [type] => nested
            [children] => Array
                (
                    [0] => Array
                        (
                            [key] => follow
                            [value] => 
                            [status] => added
                        )

                    [1] => Array
                        (
                            [key] => setting1
                            [value] => Value 1
                            [status] => not changed
                        )

                    [2] => Array
                        (
                            [key] => setting2
                            [value] => 200
                            [status] => removed
                        )

                    [3] => Array
                        (
                            [key] => setting3
                            [oldValue] => 1
                            [newValue] => 
                            [status] => changed
                        )

                    [4] => Array
                        (
                            [key] => setting6
                            [type] => nested
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [key] => doge
                                            [type] => nested
                                            [children] => Array
                                                (
                                                    [0] => Array
                                                        (
                                                            [key] => wow
                                                            [oldValue] => 
                                                            [newValue] => so much
                                                            [status] => changed
                                                        )

                                                )

                                        )

                                    [1] => Array
                                        (
                                            [key] => key
                                            [value] => value
                                            [status] => not changed
                                        )

                                    [2] => Array
                                        (
                                            [key] => ops
                                            [value] => vops
                                            [status] => added
                                        )

                                )

                        )

                    [5] => Array
                        (
                            [key] => setting4
                            [value] => blah blah
                            [status] => added
                        )

                    [6] => Array
                        (
                            [key] => setting5
                            [value] => Array
                                (
                                    [key5] => value5
                                )

                            [status] => added
                        )

                )

        )

    [1] => Array
        (
            [key] => group1
            [type] => nested
            [children] => Array
                (
                    [0] => Array
                        (
                            [key] => baz
                            [oldValue] => bas
                            [newValue] => bars
                            [status] => changed
                        )

                    [1] => Array
                        (
                            [key] => foo
                            [value] => bar
                            [status] => not changed
                        )

                    [2] => Array
                        (
                            [key] => nest
                            [oldValue] => Array
                                (
                                    [key] => value
                                )

                            [newValue] => str
                            [status] => changed
                        )

                )

        )

    [2] => Array
        (
            [key] => group2
            [value] => Array
                (
                    [abc] => 12345
                    [deep] => Array
                        (
                            [id] => 45
                        )

                )

            [status] => removed
        )

    [3] => Array
        (
            [key] => group3
            [value] => Array
                (
                    [fee] => 100500
                    [deep] => Array
                        (
                            [id] => Array
                                (
                                    [number] => 45
                                )

                        )

                )

            [status] => added
        )

)
И вот их я не знаю как переформатировать в строку. Нужен точно вот такой результат:
Код
{
    common: {
      + follow: false
        setting1: Value 1
      - setting2: 200
      - setting3: true
      + setting3: null
      + setting4: blah blah
      + setting5: {
            key5: value5
        }
        setting6: {
            doge: {
              - wow: 
              + wow: so much
            }
            key: value
          + ops: vops
        }
    }
    group1: {
      - baz: bas
      + baz: bars
        foo: bar
      - nest: {
            key: value
        }
      + nest: str
    }
  - group2: {
        abc: 12345
        deep: {
            id: 45
        }
    }
  + group3: {
        fee: 100500
        deep: {
            id: {
                number: 45
            }
        }
    }
}
Тоже как то циклом перебирать массив, рекурсивно углубляясь внутрь? Если идти в глубину, то надо как то накапливать данные с верхних уровней и записывать в результат, а если это делать рекурсивно то могут быть ошибки так как полученный результат будет уже строкой, а углубляясь в массив и вытаскивая оттуда данные которые тоже могут быть массивом - будет ошибка при записи массива в строку. Помимо всего прочего нужна еще и сортировка, сортировка должна быть по ключам в алфавитном порядке. Никак не могу сообразить как это реализовать =(

Код для сбора данных:

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function diffData($firstFile, $secondFile)
{
    $firstFile = json_decode(json_encode($firstFile), true);
    $secondFile = json_decode(json_encode($secondFile), true);
    $uniqueKeys = array_keys(array_merge($firstFile, $secondFile));
    $data = array_map(function ($key) use ($firstFile, $secondFile) {
        // если текущий ключ не существует в первом файле, но присутствует во втором
        if (!array_key_exists($key, $firstFile)) {
            return ['key' => $key, 'value' => $secondFile[$key], 'status' => 'added'];
        // если текущего ключа нет во втором файле, (логично что он есть в первом)
        } elseif (!array_key_exists($key, $secondFile)) {
            return ['key' => $key, 'value' => $firstFile[$key], 'status' => 'removed'];
        }
        $nodeFirst = $firstFile[$key];
        $nodeSecond = $secondFile[$key];
        if (is_array($nodeFirst) === true && is_array($nodeSecond) === true) {
            $children = diffData($nodeFirst, $nodeSecond);
            $arr = ['key' => $key, 'type' => 'nested', 'children' => $children];
            usort($arr['children'], function ($a, $b) {
                return substr($a['key'], 0, 1) <=> substr($b['key'], 0, 1);
            });
            return $arr;
        }
        if ($nodeFirst === $nodeSecond) {
            return  ['key' => $key, 'value' => $nodeFirst, 'status' => 'not changed'];
        } else {
            return ['key' => $key, 'oldValue' => $nodeFirst, 'newValue' => $nodeSecond, 'status' => 'changed'];
        }
    }, $uniqueKeys);
    //print_r($data);
    return $data;
}
Заранее спасибо!
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.01.2021, 17:57
Ответы с готовыми решениями:

Отформатировать файл с программой на языку С. ( вложенные циклы, if_else)
Отформатировать файл с программой на языку С. ( вложенные циклы, if_else)

Отформатировать файл с программой на языке С. ( вложенные циклы, if_else)
Отформатировать файл с программой на языке С. ( вложенные циклы, if_else) вот прога для первых...

Вложенные массивы js
Всем здравствуйте! Буду очень благодарен, если объясните новичку (всего лишь месяц, чуть меньше...

Вложенные массивы
Наткнулся на проблему. У меня массивы вложены в друг-друга. Получить значение из такого массива я...

1
867 / 598 / 275
Регистрация: 31.08.2019
Сообщений: 1,722
19.01.2021, 03:28 2
Цитата Сообщение от kib0rg Посмотреть сообщение
перебирать массив, рекурсивно
Без сортировки попробовал, как вариант, обойти один массив, ... слегка изменив и создав дополнительный,
и при выводе обходить второй.
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<?php
$arr1 = json_decode(file_get_contents('./test.json'), 1);
$arr2 = yaml_parse_file('./test.yml');
//echo "<?\n\$arr1 = ", var_export($arr1, 1), "\n\$arr2 = ", var_export($arr2, 1), "\n\n";
 
/* ####### вроде мб вариант с array_merge_recursive()
 
$arr3 = array_merge_recursive($arr1, $arr2);
echo "<?\n\$arr1 = ", var_export($arr1, 1), "\n\$arr2 = ", var_export($arr2, 1),
    "\n\$arr3 = ", var_export($arr3, 1), "\n\n";
*/
function  xsign(&$old, &$new) { ##### array ##### все случаи кроме удаления
    $sign = array();
    foreach($new AS $k => $v){
        if (isset($old[$k])) {
            if (is_array($v)) {
                if (!is_array($old[$k]))    $sign[$k] = 'x'; # разный тип перезапись
                else            $sign[$k] = xsign($old[$k], $v); # рекурсия
            }
            elseif(is_array($old[$k]) || $v != $old[$k])        $sign[$k] = 'x'; # перезапись
            else                $sign[$k] = '='; # без изменений
        }
        else {
            $sign[$k] = '+'; # добавление
            $old[$k] = $v;
        }
    }
    return $sign;
}
function xx($lvl) {
    return str_repeat('  ', $lvl);
}
function  xout(&$old, &$new, $sgn, $lvl = 1) { ##### array
    foreach($old AS $k => $v){
        if (isset($sgn[$k]) && !is_array($sgn[$k])) {
            switch($sgn[$k]){
            case 'x':
                echo ' - ', xx($lvl),'"', $k, '";' , json_encode($v), ",\n";
            case '+':
                echo ' + ', xx($lvl),'"', $k, '";' , json_encode($new[$k]), ",\n";
            break;
            case '=':
                echo '   ', xx($lvl),'"', $k, '";' , json_encode($v), ",\n";
            }
        }
        elseif (is_array($v)) {
            if (!isset($new[$k])) {
                echo ' - ', xx($lvl),'"', $k, '";' , json_encode($v), ",\n";
                continue;
            }
            echo xx($lvl-1),'"', $k, '":{',"\n";
            xout($v, $new[$k], $sgn[$k], $lvl+1);
            echo xx($lvl-1),'}',"\n";
        }
        else {
            echo ' - ', xx($lvl),'"', $k, '";' , json_encode($v), ",\n";
        }
    }
}
 
xout($arr1, $arr2, xsign($arr1, $arr2));
Сильно не присматривался ... возможно есть баги/ошибки/опечатки/бессмыслицы
Код
"common":{
       "setting1";"Value 1",
 -     "setting2";200,
 -     "setting3";true,
 +     "setting3";null,
  "setting6":{
         "key";"value",
    "doge":{
 -         "wow";"",
 +         "wow";"so much",
    }
 +       "ops";"vops",
  }
 +     "follow";false,
 +     "setting4";"blah blah",
 +     "setting5";{"key5":"value5"},
}
"group1":{
 -     "baz";"bas",
 +     "baz";"bars",
       "foo";"bar",
 -     "nest";{"key":"value"},
 +     "nest";"str",
}
 -   "group2";{"abc":12345,"deep":{"id":45}},
 +   "group3";{"fee":100500,"deep":{"id":{"number":45}}},
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.01.2021, 03:28

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

Вложенные массивы
Добрый день. Нужно делать класс Student, полями в котором будут: name, unattended, sick_note....

Вложенные массивы
questiоn = , , , ] ]; как задать такой массив??? напр. мне нужно 18 вопросов сделать, а...

Вложенные массивы
Ребята помогите закрыть последний предмет в заочке, все сдал кроме ассемблера, уж больно много...

DBXJSON и вложенные массивы
Всем привет! Подскажите как получить значения во вложенных массивах json. Имею такую строку json ...

массивы и вложенные структуры
есть такой код: struct part1 { int arr; }; struct part2 { part1 dim; };

массивы и Вложенные циклы
Помогите пожалуйста решить очень нужно!!!! 5 задач нужно через 2 дня сдавать я не могу написать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.