Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Найти максимально близкое минимальное число из многомерного массива (https://javascript.ru/forum/misc/73041-najjti-maksimalno-blizkoe-minimalnoe-chislo-iz-mnogomernogo-massiva.html)

the_little 16.03.2018 15:38

Найти максимально близкое минимальное число из многомерного массива
 
Здравствуйте.

Есть многомерный массив.

Например

priceArr = [
['0', '10', '20', '30', '40', '50'],
['10', '100', '200', '300', '400', '500'],
['20', '101', '201', '301', '401', '501'],
['30', '102', '202', '302', '402', '502'],
['40', '103', '203', '303', '403', '503'],
['50', '104', '204', '304', '404', '504'],
];

В данном массиве первая "строка" - ширина
первый "столбец" - высота.

Соответсвенно пользователь задает 2 значения. Например высота 31, ширина 29.

Нужно для ширины найти максимально близкое значение из первой "строки", но чтобы оно было меньше заданного, и вернуть индекс в массиве, сохранив его например в переменную "b".
Сделать то же для высоты, только теперь найти максимально близкое значение из первого "столбца", но чтобы оно было меньше заданного, и вернуть индекс массива, сохранив его например в переменную "a".

Ну и вывести значение priceArr[a][b]

В данном примере, высота 31 должна вернуть индекс массива = 3, так как ближайшее наименьшее значение равно 30.
А ширина 29 должна вернуть индекс в массиве = 2, так как наименьшее ближайшее значение = 20.

И соответственно при заданных условиях попадаем в priceArr[3][2], что должно вернуть нам 202.

ksa 16.03.2018 16:10

Цитата:

Сообщение от the_little
Нужно для ширины найти максимально близкое значение из первой "строки", но чтобы оно было меньше заданного, и вернуть индекс в массиве, сохранив его например в переменную "b".
Сделать то же для высоты, только теперь найти максимально близкое значение из первого "столбца", но чтобы оно было меньше заданного, и вернуть индекс массива, сохранив его например в переменную "a".

Это одно из стандартных заданий по массивам и циклам...
В чем у тебя возникло затруднение?

j0hnik 16.03.2018 16:40

var priceArr = [
['0', '10', '20', '30', '40', '50'],
['10', '100', '200', '300', '400', '500'],
['20', '101', '201', '301', '401', '501'],
['30', '102', '202', '302', '402', '502'],
['40', '103', '203', '303', '403', '503'],
['50', '104', '204', '304', '404', '504'],
];

var func =(arr,w,h) => arr[arr[0].findIndex(el=>el>w)-1][arr.findIndex(el=>el[0]>h)-1];

console.log(func(priceArr,31,29));

В одну строчку ваша задача решается.

рони 16.03.2018 16:51

:-?
function fn(w,h) {
var priceArr = [
['0', '10', '20', '30', '40', '50'],
['10', '100', '200', '300', '400', '500'],
['20', '101', '201', '301', '401', '501'],
['30', '102', '202', '302', '402', '502'],
['40', '103', '203', '303', '403', '503'],
['50', '104', '204', '304', '404', '504'],
];

return  priceArr[w/10|0][h/10|0]
}

alert(fn(31,29));

Dilettante_Pro 16.03.2018 18:06

function fn(w,h) {
var priceArr = [
['0', '10', '20', '30', '40', '50'],
['10', '100', '200', '300', '400', '500'],
['20', '101', '201', '301', '401', '501'],
['30', '102', '202', '302', '402', '502'],
['40', '103', '203', '303', '403', '503'],
['50', '104', '204', '304', '404', '504'],
];

return  priceArr[~~(w/10)][~~(h/10)]
}

alert(fn(31,29));

the_little 16.03.2018 18:18

Всем огромное спасибо!

А я все примеры что находил сделаны были совсем по другому. И там простой массив был.

Там находили расстояния от заданного значения, до всех знаний, и искали наименьшее. И таким образом находили ближайшее, но не стояла задача искать ближайшее минимальное.

Dilettante_Pro 16.03.2018 18:21

the_little,
Главное - что у тебя массив сортированный, так что тут и искать нечего.

the_little 17.03.2018 20:41

Забацал на сайте такую функцию.
Всего 4 массива. Для примера вставляю 2, поскольку 4 - пишет слишком много))
Первый считает отлично, как надо.
Второй массива считает вообще что-то не то. В чем проблема не могу понять.

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

Можете подсказать куда смотреть... Все 4 массива делал из экселевских таблиц, сохранял в csv.

var price1Arr = [
    [0,1750,1875,2000,2125,2250,2375,2500,2625,2750,2875,3000,3125,3250,3375,3500,3625,3750,3875,4000,4125,4250,4375,4500,4625,4750,4875,5000,5125,5250,5375,5500,5625,5750,5875,6000],
    [1750,38785,39677,40479,41906,43421,46811,47968,49217,50554,49931,50644,53587,58044,62323,66694,69814,68565,71507,75965,77570,76144,80068,84169,85416,83721,87825,91568,93531,93531,95492,101466,107618,106547,108509,113770],
    [1875,40034,40748,43628,45405,46810,49337,50462,52990,53176,54580,54301,57481,62071,66752,71432,70973,69724,72667,77214,78818,77394,81227,85240,86665,84793,88805,92818,94688,94688,96562,102535,108777,107618,109579,114841],
    [2000,41192,44002,46342,43456,44061,41984,44840,46659,49169,53930,57046,58085,58950,62414,65703,72131,72844,75965,78284,80691,80068,84793,86396,88716,88448,92907,93799,96829,98791,100664,102268,106638,108687,114126,110293],
    [2125,45124,45875,43282,43628,44581,42503,45014,46918,49515,52371,55056,57912,58950,58776,61722,70883,72042,72757,75074,79086,79978,80068,82652,87735,89339,89963,91391,93173,97096,104052,96741,102624,106638,119120,105121],
    [2250,46625,44061,44061,44061,44927,43370,45014,46745,49775,51678,54536,57305,60249,58776,62739,70259,72131,70617,73558,75520,78998,77838,80869,85240,88716,87110,89519,91836,98345,106103,97008,101288,108154,121349,105479],
    [2375,47746,44927,47177,48044,48649,46745,46311,48564,49429,54275,56959,60162,64663,58863,68655,72577,76233,72131,75163,78640,82564,79086,81672,86577,91659,84257,87557,93709,102359,118139,103605,110026,118675,131603,113859],
    [2500,51022,48217,50640,51419,52111,55575,48737,51678,55575,55056,57998,62154,67438,82207,86042,85595,87468,89608,90766,92907,95135,97008,102535,105656,105300,110381,112522,114929,117157,121795,129374,131781,134188,139360,141767],
    [2625,52146,49169,51074,51938,52805,57393,49255,51852,56267,56095,59125,62244,73202,83276,86396,88270,88627,93263,93709,94512,96473,99148,104052,106994,108241,113324,118049,117961,120012,127501,132940,135168,137665,145958,145511],
    [2750,53831,50814,51246,52286,52718,57219,50120,52805,56959,55977,58617,67674,73202,84080,88448,87735,88538,95135,96741,97632,98791,102446,106906,107440,108777,115375,119030,121081,123934,131068,133652,137488,141410,149880,148186],
    [2875,59076,55661,58604,59642,61028,62846,57046,59729,64801,66158,81227,82564,83276,88360,92907,93975,96205,98702,107618,106906,106906,110203,114395,115999,118675,120636,125718,130622,133207,138647,144175,148543,151040,155497,161474],
    [3000,60666,57305,60076,61115,61374,66135,70723,69004,75965,82119,80246,82921,85327,93531,98435,99683,102091,108422,113146,112433,113770,116980,121706,122152,124826,128392,132584,137933,140341,148989,155051,159778,162542,167269,171814],
    [3125,62487,59024,61878,62948,63215,68119,72845,76867,78244,84581,82653,85407,87888,96337,101387,102674,105153,111675,116541,115807,117183,120489,125357,125816,128571,132244,136560,142071,144550,153457,159702,164571,167418,172287,176968],
    [3250,64362,65750,68929,70120,70418,75881,81144,79173,80591,87119,85133,87971,90524,99227,104429,105754,108308,115025,120037,119280,120698,124104,129119,129591,132429,136211,140657,146334,148887,158062,164493,169509,172441,177456,182277],
  ];

  var pr4arr = [
    [0,2110,2250,2375,2500,2625,2750,2875,3000,3125,3250,3375,3500,3625,3750,3875,4000,4125,4250,4375,4500,4625,4750,4875,5000],
    [1700,48402,50153,54067,55404,56846,58391,57671,58494,61894,67041,71983,77032,80636,79193,82590,87739,89595,87945,92478,97214,98656,96699,101437,105762],
    [1800,52444,54065,56984,58284,61204,61418,63041,62717,66390,71692,77099,82504,81974,80532,83930,89182,91036,89390,93817,98453,100097,97935,102569,107204],
    [1900,51808,52963,53120,55483,58003,59629,63304,65036,67450,70547,75273,79891,82643,82334,85835,89800,92117,90933,95875,99119,101282,100046,104938,107771],
    [2000,50191,50890,48491,51790,53891,56790,62289,65888,67088,68088,72089,75887,83310,84136,87739,90418,93199,92478,97935,99788,102467,102157,107308,108338],
    [2100,50291,51246,48737,51938,54104,57046,61462,64751,67001,68126,70030,73580,82564,83634,85952,88538,92283,92372,95225,97632,101912,102714,105656,106906],
    [2125,50391,51506,49169,52026,54190,57219,60508,63626,66828,68126,67865,71330,81940,83188,84080,86665,91301,92372,92460,95403,101288,103159,103874,105566],
    [2250,50890,51938,50120,52026,54015,57479,59729,63019,66222,69597,67865,76091,81137,83276,81583,84972,87200,91213,89963,93353,98435,102535,100664,103337],
    [2375,55491,56180,54015,53498,56095,57133,62673,65788,69512,74619,71415,79353,83902,88092,83276,86843,90855,95315,91301,94334,100040,105835,97277,101110],
    [2500,59389,60162,64145,56267,59729,64145,63626,67001,71762,81803,94956,99326,98879,101020,103517,104854,107261,109847,111987,118495,121973,121616,127501,129997],
    [2550,59688,60595,65270,56527,59817,64577,64145,67607,73580,84348,95492,99594,100397,101733,105656,106547,108241,110650,113324,119299,122775,123311,129195,133207],
    [2625,59989,61028,66308,56873,59902,65012,64751,68300,77748,84524,96205,99771,102000,102359,107708,108241,109134,111452,114573,120191,123578,125094,130977,136328],
    [2700,60390,60855,66048,57912,61028,65788,67865,71156,78195,84524,97096,102180,101288,102268,109847,111720,112789,114037,118318,123488,124114,125628,133297,137488],
    [2850,68886,70463,72542,65876,69079,78601,76412,93888,95315,96205,102091,107261,108599,111095,113950,124290,123488,123488,127322,132137,134010,137131,139360,145244],
    [2975,69737,70637,74445,73840,76350,84348,85595,93263,95492,97364,105033,110561,111809,114573,119654,127501,126698,127411,131244,136328,137488,140608,143817,149167],
    [3000,70587,70810,76350,81717,86219,87825,94867,92728,95848,98612,107975,113682,115107,117873,125272,130622,129820,131424,135168,140520,141143,144175,148276,153090],
    [3150,80989,81333,87642,93722,91445,93083,100623,98329,101606,104554,114607,120615,122147,125096,132854,138642,137768,139406,143339,149132,149677,152955,157325,162460],
  ];

  var func =(arr,h,w) => arr[arr[0].findIndex(el=>el>h)-1][arr.findIndex(el=>el[0]>w)-1];

  console.log(func(price1Arr,2000,3000));
  console.log(func(price1Arr,3000,3000));
  console.log(func(pr4arr,2000,3000));
  console.log(func(pr4arr,3000,3000));

j0hnik 17.03.2018 20:42

Ворота считать собрались?

the_little 17.03.2018 20:46

Цитата:

Сообщение от j0hnik (Сообщение 480820)
Ворота считать собрались?

Ага

the_little 17.03.2018 20:56

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

console.log(pr4arr[5][5]);
  console.log(pr4arr[3][7]);


Т.е. просто функция почему то отрабатывает некорректно.

j0hnik 17.03.2018 21:02

w и h специально переставили?

the_little 17.03.2018 21:14

Цитата:

Сообщение от j0hnik (Сообщение 480823)
w и h специально переставили?

Да, я когда начал просматривать результаты, понял что он высоту и ширину местами меняет. Почему не понял. Если смотреть код, вроде все как надо, но выдавал наоборот.

the_little 17.03.2018 21:22

Попробовал так

var func =(arr,w,h) => arr[arr.findIndex(el=>el[0]>h)-1][arr[0].findIndex(el=>el>w)-1];
  console.log(func(price1Arr,2000,3000));


Первый массив считает правильно, второй нет...

the_little 17.03.2018 21:24

А так считает правильно все массивы, но ширина с высотой перепутаны получаются...
var func =(arr,w,h) => arr[arr.findIndex(el=>el[0]>w)-1][arr[0].findIndex(el=>el>h)-1];
  console.log(func(price1Arr,2000,3000));

the_little 17.03.2018 21:35

можно конечно в последнем случае убрать из функции w и h, сделать вместо них a и b, и просто передавать наоборот значения))

the_little 17.03.2018 21:41

Так пока оставил. Считает все массивы правильно.
var func =(arr,a,b) => arr[arr.findIndex(el=>el[0]>a)-1][arr[0].findIndex(el=>el>b)-1];
  console.log(func(pr4arr,2000,3000)); // 2000 - высота, 3000 - ширина
  console.log(func(pr4arr,3000,2200)); // 3000 - высота, 2200 - ширина
  console.log(func(pr4arr,1700,4000)); // 1700 - высота, 4000 - ширина

j0hnik 17.03.2018 22:40

var func =(arr,w,h) => arr[arr.findIndex(el=>el[0]>w)-1][arr[0].findIndex(el=>el>h)-1];

var func =(arr,a,b) => arr[arr.findIndex(el=>el[0]>a)-1][arr[0].findIndex(el=>el>b)-1];


неужели результат поменялся?

j0hnik 17.03.2018 22:54

а в excel откуда импортировали?

the_little 17.03.2018 23:08

Цитата:

Сообщение от j0hnik (Сообщение 480832)
var func =(arr,w,h) => arr[arr.findIndex(el=>el[0]>w)-1][arr[0].findIndex(el=>el>h)-1];

var func =(arr,a,b) => arr[arr.findIndex(el=>el[0]>a)-1][arr[0].findIndex(el=>el>b)-1];


неужели результат поменялся?

Не, результат не поменялся. Просто w - ширина, h - высота.
А когда задаются значения - то получается чтобы получить правильный ответ, нужно сделать w - высота, h - ширина. И чтобы не путаться, просто переименовал переменные.

the_little 17.03.2018 23:09

Цитата:

Сообщение от j0hnik (Сообщение 480833)
а в excel откуда импортировали?

Я брал прайс, из него копировал часть данных в отдельную книгу Эксель, сохранял в csv.

j0hnik 17.03.2018 23:49

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

the_little 19.04.2018 14:26

Цитата:

Сообщение от j0hnik (Сообщение 480836)
the_little,
Понятно, я сталкивался с похожим калькулятором непрактичный жуть, изменились цены на комплектующие маленькие ворота дорожают сильней, и сиди возись, а был бы норм алгоритм (с исходной программы) просто правиш определенный коэффициент и все. (потому как бухгалтера эти таблицы составлять особо не спешат) у них типа своих забот полон рот

Сейчас по окнам делаю. Так там размеры от 500 до 2000+ метров. С шагом 10мм. И по каждому типу (1-2-3 створки, эконом, стандарт, премиум) свои таблицы...
Я конечно сделал через парсер считывание этих таблиц. Но все равно не понимаю, как так можно считать...
Ну там же площадь. Сделать расчет от площади + коэффициенты какие-нибудь и все...
Я не представляю как будут эти таблицы перечитывать))

the_little 19.04.2018 14:29

Возник вопрос с поиском нужного элемента в массива.
Вот код, которым пользуюсь.
function checkArr(arr,a,b) {
      return arr[arr.findIndex(el=>el[0]>a)-1][arr[0].findIndex(el=>el>b)-1];
    }

Я так понимаю смысл такой. Находится элемент который больше заданного значения, и потом индекс уменьшается на 1.
Тогда задача так и стояла, если значение попадает между 2-х заданных, считать по меньшему.
Все работает как надо.

Сейчас задача обратная. Считать по большему.
Я попробовал изменить функцию на такую (вроде как должен искать меньшее и потом индекс увеличивать на 1), но выдает всегда минимальное значение...
function checkArr(arr,a,b) {
      return arr[arr.findIndex(el=>el[0]<a)+1][arr[0].findIndex(el=>el<b)+1];
    }

the_little 19.04.2018 14:34

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

МОжно ему как то сказать, чтобы он от максимального значения шел?

the_little 19.04.2018 14:39

блин, там же просто можно убрать -1

the_little 19.04.2018 14:42

return arr[arr.findIndex(el=>el[0]>=a)][arr[0].findIndex(el=>el>=b)];

the_little 19.04.2018 14:55

заметил непонятный баг
Диапазон ширины в одном массиве 600-1800.
Пока задается ширина меньше 1000, считает нормально. Как только вписываешь 1000 или больше - выдает первый столбец...

Как такое может быть?

the_little 19.04.2018 15:06

Проверил на первой функции, которая на другом массиве работала нормально.
function checkArr(arr,a,b) {
      return arr[arr.findIndex(el=>el[0]>a)-1][arr[0].findIndex(el=>el>b)-1];
    }


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

the_little 19.04.2018 15:21

Дело не в парсере... Массив проверил. в многомерном массиве 52 массива, в каждом 122 элемента.
Запросил data[51][121] - выдал правильное угловое значение. Т.е. весь массив заносится там куда-то. парсится таблица нормально.
Видимо в функции какая-то проблема, но в чем понять не могу.

рони 19.04.2018 15:55

the_little,
вангую, что в ваших массивах строки, а не числа, в этом и проблема.
в парсере не хватает + или parseInt

j0hnik 19.04.2018 16:47

function checkArr(arr,a,b) {
      return arr[arr.findIndex(el=>el[0]*1>a*1)-1][arr[0].findIndex(el=>el*1>b*1)-1];
    }


вот так попробуйте

the_little 19.04.2018 17:03

Цитата:

Сообщение от рони (Сообщение 483633)
the_little,
вангую, что в ваших массивах строки, а не числа, в этом и проблема.
в парсере не хватает + или parseInt

Проверю. почему то до 980 срабатывает, а дальше не работает...
Там вроде были какие-то настройки по поводу числе.
Посмотрю.
Спасибо!

the_little 19.04.2018 17:07

Цитата:

Сообщение от j0hnik (Сообщение 483646)
function checkArr(arr,a,b) {
      return arr[arr.findIndex(el=>el[0]*1>a*1)-1][arr[0].findIndex(el=>el*1>b*1)-1];
    }


вот так попробуйте

РАБОТАЕТ!!!
Я правильно понимаю, что умножением на 1 мы как бы говорим что там число, и из-за этого работает?

Т.е. все дело в формате?

рони 19.04.2018 17:12

Цитата:

Сообщение от the_little
Т.е. все дело в формате?

alert("980">"1000")

j0hnik 19.04.2018 17:22

Цитата:

Сообщение от the_little (Сообщение 483649)
РАБОТАЕТ!!!
Я правильно понимаю, что умножением на 1 мы как бы говорим что там число, и из-за этого работает?

преобразуем строку в число.
alert(typeof '1')

alert(typeof ('1'*1))

the_little 19.04.2018 17:42

Понял! Огромное спасибо!


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