Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   перебор массива с отступом (https://javascript.ru/forum/misc/59093-perebor-massiva-s-otstupom.html)

Brook 27.10.2015 16:53

перебор массива с отступом
 
Добрый день,
Кто-нибудь знает как называется алгоритм который перебирает точки массива (матрицы) с отступом или по кругу не знаю как точно описать. Пример:

МАССИВ
[01, 02, 03, 04]
[05, 06, 07, 08]
[09, 10, 11, 12]
[13, 14, 15, 16]

На выходе перебора с шагом 1 (4 массива 2х2):
#1        |   #2
[01, 02]  |  [03, 04]
[05, 06]  |  [07, 08]
----------+-----------
#3        |   #4
[09, 10]  |  [11, 12]
[13, 14]  |  [15, 16]


На выходе перебора с шагом 2 (1 массив 2х2):
#1       

[01, 03]
[09, 11]


На выходе перебора с шагом 3 (1 массив 2х2):
#1       

[01, 04]
[13, 16]



P.S. - обернул в [html] что бы не потерять отступы... не обращайте на это внимание
P.P.S. - Для тех кто не знает как читать многомерные массивы добавил рамки

Brook 27.10.2015 17:23

так сделать сам я сдела но может что знает вариант получше а то этот какой то деревянный

var arr = [[1,2,3,4],
           [5,6,7,8],
           [9,10,11,12],
           [13,14,15,16]
           ],
    step = 1;
for(i=0; i < 4; i=i+step*2) {
	for(j=0; j < 4; j=j+step*2) {
    	var dot1 = arr[i][j],
            dot2 = arr[i][j+step],
            dot3 = arr[i+step][j],
            dot4 = arr[i+step][j+step];
        alert("Section" + (i+j) + ": [" + dot1 + ", " + dot2 + ", " + dot3 + ", " + dot4 + "]");
	}
}

laimas 27.10.2015 17:23

array.slice()

Brook 27.10.2015 17:25

laimas,
и как это поможет с двумерным массивом?!
а если шаг будет не еденица а 3 тогда как?!

laimas 27.10.2015 17:31

Какая разница какой он у вас, вам же нужно получать срезы массива, что и делает slice(), указывайте необходимую длину, получайте, выводите, и также в цикле.

На php можно было бы и короче, одной функций можно разбить массив на массивы по N элементов сразу.

Brook 27.10.2015 17:33

не не мне нужны только крайние точки а не срезы... в этом то и вся разница
то есть если следовать примеру из Топика то если установить шаг 3, тогда вернется массив:
[
 [1,4]
 [13,16]
]

конечно можно получить крайние точки но что делать с точками ниже?... хммм ну в общем да можно использовать слайс.. ок = спасибо ... но всеже это не совсем то

laimas 27.10.2015 17:42

Цитата:

Сообщение от Brook
но всеже это не совсем то

Оригинально:

[01, 02, 03, 04]
...

На выходе перебора (4 массива 2х2): показать чистый исходник в новом окне Скрыть/показать номера строк печать кода с сохранением подсветки

#1 #2
[01, 02] [03, 04]
....

Что здесь тогда крайнее? )

Brook 27.10.2015 18:30

Цитата:

(4 массива 2х2)
массив №1 [[01,02][05,06]]
массив №2 [[03,04][07,08]]
массив №3 [[09,10][13,14]]
массив №4 [[11,12][15,16]]

Надеюсь тперь понятнее )

laimas 27.10.2015 18:44

Изначально так и надо было написать. Ну и в чем проблема - зная вложения массива, получать по их индексам их срезы, четные и нечетные?

рони 27.10.2015 18:58

Цитата:

Сообщение от laimas
Ну и в чем проблема - зная вложения массива, получать по их индексам их срезы, четные и нечетные?

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

laimas 27.10.2015 19:21

Цитата:

Сообщение от рони
не понимаю причём тут чётность

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

рони 27.10.2015 19:35

laimas,
не очень понимаю как очень просто брать эти срезы
вариант решения
function matrix(c, d) {
    for (var g = [], a = 0; a < d * d; a += c) {
        for (var f = [], e = [], b = 0; b < c; b++) e.push(a + b + 1);
        f.push(e);
        for (b = 0; b < c - 1; b++) e = e.map(function(a) {
            return a + d
        }), f.push(e);
        g.push(f);
        !a || (a + c) % d || (a += d * (c - 1))
    }
    return g
};
alert(JSON.stringify(matrix(2,4)))// матрицу 4 на 4 разбить 2 на 2
alert(JSON.stringify(matrix(3,9)))//этоn же вариант и для матрицы 9 на 9 на 3 на 3 ... matrix(3,9)

laimas 27.10.2015 20:06

var a = [
    ['01', '02', '03', '04'],
    ['05', '06', '07', '08'],
    ['09', '10', '11', '12'],
    ['13', '14', '15', '16']
], b = [], i, s = 2;

for(i=0; i<a.length/2; i++) {
    b.push(a[i].slice(0, s), a[i+1].slice(0, s));
    b.push(a[i].slice(s), a[i+1].slice(s))
}

console.log(b)


Ну естественно, если входной массив с произвольной длиной вложений и срезов которые нужно взять, то вычисляем эти условия.

laimas 27.10.2015 20:35

Кстати, рони, а то так и забуду. Интересная вещь совсем недавно приключилась с этим: $('selector')[0].

У заказчика несколько машин, одни работают под XP SP3, есть и семерки и одна под win 8.1.

Возникла проблема - на одной из машин работающей под XP SP3 не загружаются файлы MS Office. Перед загрузкой клиент проверяет файл на разрешенный к загрузке тип (чисто сервис, дабы файлы). В реальности вывод ошибок сервера заблокирован и разрешен только в режиме отладки. JS-сценарий сжат.

Спрашиваю, что в этом случае выдает браузер? Ответ - Ошибка. Зная что такого сообщения нет в коде, уточняю, что за ошибка. Ответ - Не разрешенный для загрузки тип файла. Это ближе к телу.

И это только на одной машине происходит. Гадания и предположения, да еще на большие расстояния пользы не принесли, поэтому отдаю ему неупакованный JS со вставленными в предполагаемых проблемных местах вставках простых, чтобы он мне мог сообщать их, а я знал по ним узкое место.

Вот тут и началось самое смешное - теперь браузер (любой) точно выдавал ошибку на строку в который и было получение DOM - $('selector')[0], не завершенный литерал, и хоть умри. А вот $('selector').get(0) без проблем. Но тогда почему это работает в сжатом JS!? :)

После удалось узнать, что причиной является то, что JS на этой машине типы файлов MS Office получить не может, то есть files[n].type есть пустая строка. И именно только такие файлы, с остальными любыми проблем нет. Почему, так и не удалось выяснить, не имея машины под рукою "лечить" на расстоянии могут только кашпировские и т.п. :)

рони 27.10.2015 21:08

laimas,
может проверку добавить if($('selector').length) ... и да замечал разницу с использованием min.js, до причины не дошёл ... просто ставил несжатую версию

рони 27.10.2015 21:11

laimas,
вот что выдал лог
[["01", "02"], ["05", "06"], ["03", "04"], ["07", "08"], ["05", "06"], ["09", "10"], ["07", "08"], ["11", "12"]]
вроде нужно так:
[[[1, 2], [5, 6]], [[3, 4], [7, 8]], [[9, 10], [13, 14]], [[11, 12], [15, 16]]]

laimas 27.10.2015 21:43

Цитата:

Сообщение от рони
да замечал разницу с использованием min.js

Нет, я не о JQ сжатой говорю, а о моем сценарии - сжатый он работает и на проблемной машине, а вот несжатый ругается на эту строку. Я конечно давал ему и "инструкции" - найди "то-то" и замени "на"... Сначала подумал, что это следствие того, что он где-то допустил при этом ошибку. Сперва просил его показать мне кусочки где изменял, вроде бы нет, затем уже весь файл мне вернуть распакованный с его изменениями - нет ошибок, но работать на проблемной машине с $('selector')[0] ни в какую не хочет, ошибка. Но в сжатом то файле ничего не меняется, все то же - $('selector')[0], вот что интересно. :) А сам $('selector') до этого действия гарантировано есть.

Цитата:

Сообщение от рони
вот что выдал лог

Ну так какая проблема вложить так как требуется? Я писал не для того чтобы как надо, а на вопрос как получить срезы :)

рони 27.10.2015 22:07

Цитата:

Сообщение от laimas
Ну так какая проблема вложить так как требуется?

если это просто, может покажешь как? :)

laimas 27.10.2015 22:35

Цитата:

Сообщение от рони
если это просто, может покажешь как?

b.push([a[i].slice(0, s), a[i+1].slice(0, s)], [a[i].slice(s), a[i+1].slice(s)])
//[[["01", "02"], ["05", "06"]], [["03", "04"], ["07", "08"]], [["05", "06"], ["09", "10"]], [["07", "08"], ["11", "12"]]] в консоли, или не то?

laimas 27.10.2015 22:38

А, есть ошибка, смещение не проверяется, ну это тоже поправимо.
А я сперва даже не обратил внимание на выделенное красным :)

nerv_ 28.10.2015 00:03

вариант...
function split(src, dist, step, row, column) {
    if (row + step < src.length) {
        dist.push([
            [src[row][column], src[row][column + step]],
            [src[row + step][column], src[row + step][column + step]],
        ]);
        if (column + step + 1 < src[0].length) {
            return split(src, dist, step, row, column + step + 1);
        } else {
            return split(src, dist, step, row + step + 1, 0);
        }
    }
    return dist;
}

var arr = [
    [1,2,3,4],
    [5,6,7,8],
    [9,10,11,12],
    [13,14,15,16]
];

console.log(split(arr, [], 1, 0, 0));
console.log(split(arr, [], 3, 0, 0));

рони 28.10.2015 00:32

nerv_,
а что нужно поставить в аргументы split чтоб получить из
var arr = [
[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,62,63],
[64,65,66,67,68,69,70,71,72 ],
[73,74,75,76,77,78,79,80,81]
];

результат
var arr=[[[1, 2, 3], [10, 11, 12], [19, 20, 21]], [[4, 5, 6], [13, 14, 15], [22, 23, 24]], [[7, 8, 9], [16, 17, 18], [25, 26, 27]], [[28, 29, 30], [37, 38, 39], [46, 47, 48]], [[31, 32, 33], [40, 41, 42], [49, 50, 51]], [[34, 35, 36], [43, 44, 45], [52, 53, 54]], [[55, 56, 57], [64, 65, 66], [73, 74, 75]], [[58, 59, 60], [67, 68, 69], [76, 77, 78]], [[61, 62, 63], [70, 71, 72], [79, 80, 81]]]

laimas 28.10.2015 09:33

var a = [
    ['01', '02', '03', '04'],
    ['05', '06', '07', '08'],
    ['09', '10', '11', '12'],
    ['13', '14', '15', '16']
], b = [], i, s = 2;

for(i = 0; i<a.length; i += s) {
    b.push([a[i].slice(0, s), a[i+1].slice(0, s)], [a[i].slice(s), a[i+1].slice(s)])
}

console.log(b)


Маленько подумать, и для любой n-размерности в итерации нужно пройтись циклом n-раз в котором уже и push().

рони 28.10.2015 10:14

матрица разбить на квадраты
 
:write: :)
оставлю тут вариант на данный момент
function matrix(c, d) {
    for (var h = [], a = 0; a < d * d; a += d * (c - 1))
        for (var f = 0; f < d; f += c) {
            for (var g = [], e = [], b = 0; b < c; b++) e.push(a + b + 1);
            g.push(e);
            for (b = 0; b < c - 1; b++) e = e.map(function(a) {
                return a + d
            }), g.push(e);
            h.push(g);
            a += c
        }
    return h
};
alert(JSON.stringify(matrix(2,4)))
alert(JSON.stringify(matrix(3,9)))
console.log(matrix(3,9))

nerv_ 28.10.2015 13:53

Цитата:

Сообщение от рони
а что нужно поставить в аргументы split чтоб получить из

придется добавить немного магии :)
как видишь, я руками в строке 03 добавляю фиксированный размер массива (2х2)

на самом деле постановка задачи никакая)
не понятно зачем вообще такие извращения

рони 28.10.2015 14:09

:-? ... мда ... видимо сделать универсальный вариант, более никому не интересно :)
laimas, шаблон в цикле
nerv_, шаблон но цикл заменён на рекурсию

laimas 28.10.2015 14:50

Цитата:

Сообщение от рони
laimas, шаблон в цикле

?

А в чем собственно проблема? Я понимаю так - задана размерность среза, которую нужно получить из массива. Получать данные нужно по смещению этой размерности среза, при чем элементы среза нужно получать не по строкам, а по колонкам массива.

Итого - итерация внешнего цикла это постоянное смещение на размерность среза по строкам массива, а итерация внутреннего цикла, это постоянное смещение на размерность среза по колонкам массива. Во внутреннем цикле получаем срез, смещение которого определяется размерностью среза для колонок и строк массива.

Лично меня жаба бы задавила гонять четыре цикла с долгими переборами и проверками. :)

Я занимаюсь разработкой шрифта, вот закончу, тогда... А все таки беден JS на готовые функции для работы с массивами.

Brook 28.10.2015 16:57

спасибо

Brook 28.10.2015 19:17

nerv_,
чутка сменил под свои нужды = спасибо, и что я тупанул и сразу не сделал рекурсию ?! - лох ))

function split(src, st, r, c) {
    if(!st) return false;
    if (r + st < src.length && c + st < src[0].length) { 
    console.log(st +"---------"+src[r][c]+","+ src[r][c + st]+","+src[r + st][c]+","+ src[r + st][c + st]);
	if (c + st +1 < src[0].length) {
            return split(src, st, r, ++c + st);
        } else {
            return split(src, st, ++r + st, 0);
        }
    } else split(src, st==1?0:Math.ceil(st/2), 0, 0);
}

var arr = [
    [1,2,3,4],
    [5,6,7,8],
    [9,10,11,12],
    [13,14,15,16]
];
split(arr, 3, 0, 0);

laimas 28.10.2015 20:20

Цитата:

Сообщение от Brook
что я тупанул и сразу не сделал рекурсию

А она тут нужна?

Brook 29.10.2015 09:26

laimas, ну я бы не сказал что нужна НО рекурсия работает быстрее чем цикл - и в моем случае больше подходит именно она...
И должен уточнить что это если не ошибаюсь это единственный алгоритм который правильно работает с шагом (с разным шагом!!!) = у Рони было хорошее решение пока я не посчитал кооличество циклов)))) - 4 это уж слишком))
Так же мне нужна была адекватная работа с переменными (идем от простого = чем проще тем лучше) - в примерах рони было просто оочень много новых переменных особенно порадовало создание массива в перевом цикле (2го примера - см. выше)... за это отдельное СПАСИБО, РОНИ потому как я бы наверное так не ухитрился бы сделать так что это было хорошим "уроком"...
Вам тоже СПАСИБО, но больше за дискут нежели за код - так как я все равно не согласен с применением slice в данном вопросе ))))
Если я найду еще вариант решения задачи - обязательно отпишусь - если нет - закрою тему. ))))

laimas 29.10.2015 10:38

Цитата:

Сообщение от Brook
НО рекурсия работает быстрее чем цикл

Классно! :lol:

А если еще раз подумать нужна ли она там, где задачей предписано смещаться (нет в массивах отступов, есть смещения) на одинаковую размерность вниз и в ширину?

алгоритм который правильно работает с шагом (с разным шагом!!!)

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

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

так как я все равно не согласен с применением slice в данном вопросе

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

nerv_ 29.10.2015 11:44

Цитата:

Сообщение от laimas
Классно!

да, почитав, что он тут пишет, я понимаю, почему у него отрицательная репутация :)

1. я сделал "через" рекурсию потому, что хотел реализовать с помощью нее (спортивный интерес)
2. нужна ли здесь рекурсия? Нет, не нужна
3. быстрее ли работает рекурсия? Нет, не быстрей
Цитата:

Сообщение от Brook
Так же мне нужна была адекватная работа с переменными (идем от простого = чем проще тем лучше) - в примерах рони было просто оочень много новых переменных

4. был у меня более-менее нормальный код, а ты из него абвгдейку сделал :)

Brook 29.10.2015 12:52

Цитата:

был у меня более-менее нормальный код, а ты из него абвгдейку сделал
... ну спорить не буду = это так,
однако, должен прояснить ситуацию - мне нужено было решение для с++(наверное зря не сказал раньше, но не думал что такая "шумиха" поднимится), поэтому и выбрал рекурсию, если отойти от этого факта тогда да slice вполне можно было бы использовать, однако должен заметить что код laimas не справляется с поставленной задачей если сменить размер смещения например с 2 на 3 , код падает:
var a = [
    ['01', '02', '03', '04'],
    ['05', '06', '07', '08'],
    ['09', '10', '11', '12'],
    ['13', '14', '15', '16']
], b = [], i, s = [B]2[/B];

for(i = 0; i<a.length; i += s) {
    b.push([a[i].slice(0, s), a[i+1].slice(0, s)], [a[i].slice(s), a[i+1].slice(s)])
}

console.log(b)

Brook 29.10.2015 12:54

Цитата:

да, почитав, что он тут пишет, я понимаю, почему у него отрицательная репутация
по мне так репутация вообще роли не играет - если вы мне "плюсанете" моя репутация станет овер 2 тасячи так что.... это не показатель(ну по мне так)
З.Ы. - а так же из-за того что я задавал много (на сегодня уже тупых) вопросов, когда только начанал изучать js, так что не считаю это трагедией
З.З.Ы - плюс ко всему у меня соотношение вопрос\ответ наверное 50\1 тагда как у вас наверное 1\1000 ))))

Brook 29.10.2015 13:59

сравнил скорости.... мда...:
http://jsperf.com/matrix-reader-with-index-offset

laimas 29.10.2015 14:15

Цитата:

Сообщение от Brook
однако должен заметить что код laimas не справляется с поставленной задачей если сменить размер смещения например с 2 на 3 , код падает:

Полная чушь, ибо нужно головой думать, а не копировать как есть то, что является просто концепцией.

Brook 29.10.2015 15:28

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

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

laimas 29.10.2015 15:46

Информация к размышлению: не существует в природе готовой функции slice(), забыли, это в принципе как то радикально изменит концепцию получения необходимых элементов массива?

Brook 20.10.2016 10:49

Готовое решение с for:
var arr = [],
    step = 5, // offset between choosen positions
    size = 11; // grid size ~ 11x11

for(i = 0; i < size; i++) { // fill array
  arr.push([]);
  var str = '';
  for(j = 0; j < size; j++) {
    arr[i][j] = i * size + j;
    str+=addZero(''+arr[i][j], 3)+', ';
  }
  console.log(str); // draw array
}

for( i = 0 ; i + size * step < arr.length * size; i+=step) { // use ' i+=step' to start from last X pos (ex. 0-1, 1-2), else use ' i+=step+1' to reduce repetition (ex. 0-1, 2-3)
  var row = Math.floor(i / size), 
      column = Math.floor(i % size);
  
      if( row == Math.floor((i + step) / size)  && row % step == 0) { 
    
      console.log(
        '-----'+
        arr[row][column]+","+ 
        arr[row][column + step]+","+
        arr[row + step][column]+","+ 
        arr[row + step][column + step]
      );
      }
  }

function addZero(str,length) { // add 0 to fill str length
  while(str.length < length) {
    str = '0'+str;
  }
  return str;
}


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