Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Перебор вложенных массивов объектов (https://javascript.ru/forum/misc/75861-perebor-vlozhennykh-massivov-obektov.html)

Epitough 12.11.2018 22:42

Перебор вложенных массивов объектов
 
Есть такое иерархическое дерево
const graph = {
  value: 65, children: [{
    value: 15,
    children: [{
      value: 55,
      children: [{
        value: 85,
        children: [{
          value: 66,
          children: [{ value: 29 }, { value: 21 }]
        }]
      }]
    }]
  }]
};

Как можно, например, найти узел с максимальным/минимальным значением, с помощью map(), reduce(). Не могу понять как "копать" вглубь

Aetae 12.11.2018 23:07

Зачем там map или reduce - хз, а так - рекурсивно.)

рони 12.11.2018 23:40

Epitough,
<script>
const graph = {
  value: 65, children: [{
    value: 15,
    children: [{
      value: 55,
      children: [{
        value: 85,
        children: [{
          value: 66,
          children: [{ value: 29 }, { value: 21 }]
        }]
      }]
    }]
  }]
};
let example = foo(graph);

function foo(elem) {
    let obj = {
        max: elem.value,
        min: elem.value
    };
    if (elem.children) {
        elem.children.map(foo).forEach(
            function(o) {
                obj.max = Math.max(obj.max, o.max);
                obj.min = Math.min(obj.min, o.min);
            }

        );

    }
    return obj;
}

document.write(JSON.stringify(example))


  </script>

Vlasenko Fedor 13.11.2018 00:23

в некоторых задачах можно (эх не красиво), но кода то мало, сейчас камни полетят :lol:
<script>
const graph = {
  value: 65, children: [{
    value: 15,
    children: [{
      value: 55,
      children: [{
        value: 85,
        children: [{
          value: 66,
          children: [{ value: 29 }, { value: 21 }]
        }]
      }]
    }]
  }]
};
const arr = JSON.stringify(graph).match(/(-?\d+)/g);
document.write(`Min: ${Math.min(...arr)}, Max: ${Math.max(...arr)}`)
 </script>

Epitough 13.11.2018 17:23

А что делает map без функции, но с аргументом. Или это, получается, рекурсия? foo не вызывается, а становится функцией callback для map? Правильно понимаю?

рони 13.11.2018 17:43

Epitough,
... обычный map с функцией ...

рони 13.11.2018 17:47

Цитата:

Сообщение от Epitough
с помощью map(), reduce().

<script>
const graph = {
    value: 65, children: [{
        value: 15,
        children: [{
            value: 55,
            children: [{
                value: 85,
                children: [{
                    value: 66,
                    children: [{ value: 29 }, { value: 21 }]
                }]
            }]
        }]
    }]
};
let example = foo(graph);

function foo(elem) {
        let obj = {
                max: elem.value,
                min: elem.value
        };
        if (elem.children) {
                elem.children.map(foo).reduce(
                        function(obj,o) {
                                obj.max = Math.max(obj.max, o.max);
                                obj.min = Math.min(obj.min, o.min);
                                return obj
                        }, obj

                );

        }
        return obj;
}

document.write(JSON.stringify(example))


    </script>

Vlasenko Fedor 13.11.2018 20:18

<script>
const graph = {
    value: 65,
    children: [{
        value: 15,
        children: [{
            value: 55,
            children: [{
                value: 85,
                children: [{
                    value: 66,
                    children: [{
                        value: 29
                    }, {
                        value: 21
                    }]
                }]
            }]
        }]
    }]
};

const foo = data => {
    let arr = [data.value]
    while (data.children) {
        data = data.children.pop();
        arr.push(data.value)
    }
    return `Min: ${Math.min(...arr)}, Max: ${Math.max(...arr)}`
}

document.write(foo(graph))
</script>

циклом while можно заменить любую рекурсию
вот и спрашивается зачем здесь map(), reduce()? :dance:

j0hnik 13.11.2018 20:35

Цитата:

Сообщение от Poznakomlus
циклом while можно заменить любую рекурсию

Прямо таки любую?

Alexandroppolus 13.11.2018 20:59

Цитата:

Сообщение от Poznakomlus (Сообщение 498476)
<script>
const graph = {
    value: 65,
    children: [{
        value: 15,
        children: [{
            value: 55,
            children: [{
                value: 85,
                children: [{
                    value: 66,
                    children: [{
                        value: 29
                    }, {
                        value: 1
                    }]
                }, {value: 888}]
            }]
        }]
    }]
};

const foo = data => {
    let arr = [data.value]
    while (data.children) {
        data = data.children.pop();
        arr.push(data.value)
    }
    return `Min: ${Math.min(...arr)}, Max: ${Math.max(...arr)}`
}

document.write(foo(graph))
</script>

циклом while можно заменить любую рекурсию
вот и спрашивается зачем здесь map(), reduce()? :dance:

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

Alexandroppolus 13.11.2018 21:00

Цитата:

Сообщение от j0hnik (Сообщение 498477)
Прямо таки любую?

цикл + рукотворный стек - вот тогда любую
каждую рекурсивную задачу можно переписать на цикл и стек, но будет мутный говнокод

рони 13.11.2018 21:02

Poznakomlus,
пост#8 в строке 13 поменяйте 29 на 1.

Epitough 13.11.2018 23:06

Извиняюсь, если это был глупый вопрос. Спасибо, пойду дальше разбираться :thanks:

Epitough 13.11.2018 23:08

Цитата:

Сообщение от Poznakomlus (Сообщение 498476)
спрашивается зачем здесь map(), reduce()? :dance:

Да я чисто для себя.

Vlasenko Fedor 14.11.2018 04:01

Цитата:

Сообщение от Alexandroppolus
но будет мутный говнокод

увы, бывает :( и от рекурсии не отказался :cray:
<script>
const graph = {
    value: 65,
    children: [{
        value: 15,
        children: [{
            value: 55,
            children: [{
                value: 85,
                children: [{
                    value: 66,
                    children: [{
                        value: 1
                    }, {
                        value: 21
                    }]
                }]
            }, {value: -30}]
        }]
    }, {
        value: -1
    }]
};

const tree = data => {
    let arr = [], cur
    while (data.children && (cur = data.children.pop())) {
        arr = arr.concat(tree(cur))
    }
    return arr.concat(data.value)
}
const arr = tree(graph)
document.write(`Min: ${Math.min(...arr)}, Max: ${Math.max(...arr)}`)

//var tree=function(a){for(var b=[],c;a.children&&(c=a.children.pop());)b=b.concat(tree(c));return b.concat(a.value)};
</script>

Epitough 18.11.2018 17:54

Я сделал нахождение среднего значение таким образом:
const average = (graph) => {
    return sum(graph) / count(graph);
};

const sum = (graph) => {
    return graph.children ? graph.children.map(sum).reduce((item1, item2) => item1 + item2, graph.value) : graph.value;
}

const count = (graph) => {
    return graph.children ? graph.children.map(count).reduce((item1, item2) => {
    return item2.value ? (item1++, item1) : item1 += item2;
    }, 1) : graph;
};

Можно ли сделать это одной функцией(один проход по дереву)?

Malleys 18.11.2018 19:39

function average({ value, children = [] }, result = { sum: 0, count: 0 }) {
	result.sum += value;
	result.count++;

	for(const child of children)
		average(child, result);

	return result.sum / result.count;
}


Часовой пояс GMT +3, время: 10:56.