Давайте разложим эту проблему. Во-первых, давайте извлекая первый элемент каждой подрешетки из пути:
function get_elts(data, idx) {
return data.map(function(v) { return v[idx]; });
}
Так
> get_elts(data, 0) // ['A', 'B', 'C']
Разложив проблему, как это имеет основополагающее значение для хорошего дизайна программы. Мы не хотим писать вещи, которые перепутывают множество проблем. В этом случае множественные проблемы заключаются в следующем: (1) получение первого элемента каждого подмассива и (2) поиск комбинаций. Если мы напишем одну рутину, которая смешивает две проблемы, то мы никогда не сможем повторно использовать ее для других вещей. Если наш босс приходит и говорит, что теперь он хочет найти все комбинации элемента второго элемента каждого подмассива, нам придется вырезать и вставлять и создавать почти дублированный код. Тогда мы будем поддерживать этот код на всю оставшуюся жизнь или, по крайней мере, до тех пор, пока мы не уйдем. Правило о факторинге делает это раньше, чем позже.
Затем создайте все комбинации любых двух массивов:
function combinations(arr1, arr2) { //create all combos of elts in 2 arrays by
return [].concat.apply( //concatenating and flattening
[], //(starting with an empty array)
arr1.map( //a list created from arr1
function(v1) { //by taking each elt and from it
return arr2.map( //creating a list from arr2
function(v2) { //by taking each element and from it
return [v1, v2]; //making a pair with the first elt
}
);
};
)
);
}
Обычно мы бы написать это более компактно. Давайте пройдем через него:
Array#concat
сочетает в себе один или несколько вещей, или элементы внутри этих вещей, если они являются массивами, в массив.
Function#apply
позволяет нам предоставить массив, который превратится в список аргументов concat
.
Array#map
создает параллельный массив arr1
, который содержит ...
- элементы, которые два-элементные массивы на основе цикла по
arr2
.
Правильно, это не JavaScript вашей матери. Это почти другой язык из стиля, в котором вы инициализируете это и устанавливаете это, и перебираете другую вещь и возвращаете что-то еще. Принимая этот стиль, мы получаем код, который является более точным, кратким, многоразовым, доказуемо правильным, удобным для будущего и, возможно, оптимизируемым.
Будущее, я имею в виду, среди прочего, ES6-friendly. Выше, можно переписать так:
combinations = (arr1, arr2) => [].concat(...arr1.map(v1 => arr2.map(v2 => [v1, v2])));
Готовьтесь, ребята и девушки, это произойдет в ваших собеседованиях довольно скоро в настоящее время. Время для перехода от jQuery.
Теперь проблема может быть выражена как:
var first_elts = get_elts(data, 0);
combinations(first_elts, first_elts);