Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Раздельный перебор массива (https://javascript.ru/forum/misc/81257-razdelnyjj-perebor-massiva.html)

Himmelin 30.10.2020 09:54

Раздельный перебор массива
 
Недавно столкнулся с задачей выборки одинаковых значений из массива с большим количеством элементов (больше тысячи). Задача была перебрать массив (например, ["green", "yellow", "blue", "green", "purple", "green"]) с помощью map и достать из него все green. Но через map довольно медленно. Есть какие-то более быстрые способы? Я слышал про какой-то метод располовинивания массива с большим количеством элементов, но гугл про это ничего толком не выдал :thanks:

voraa 30.10.2020 10:22

Цитата:

Сообщение от Himmelin
с помощью map

С помощью функции map? А при чем тут она при поиске? Есть функция .filter

Цитата:

Сообщение от Himmelin
с большим количеством элементов (больше тысячи).

Задачи конечно разные бывают, но на мой взгляд десятки тысяч это фигня.
Цитата:

Сообщение от Himmelin
Я слышал про какой-то метод располовинивания массива

Ну есть метод поиска делением пополам, но он применяется к отсортированным массивам.

Himmelin 30.10.2020 10:31

Есть какая-нибудь ссылка на статью про метод деления пополам?

Nexus 31.10.2020 01:07

Бенчмарк производительности методов перебора: https://jsben.ch/6S3sP (у меня всегда разный результат).

Цитата:

Сообщение от voraa
Ну есть метод поиска делением пополам, но он применяется к отсортированным массивам.

Вы про бинарный поиск? Он разве не неприменим в описанной выше задаче?

Alexandroppolus 31.10.2020 10:38

Цитата:

Сообщение от Nexus
Вы про бинарный поиск? Он разве не неприменим в описанной выше задаче?

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

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

voraa 31.10.2020 10:45

Цитата:

Сообщение от Nexus
Вы про бинарный поиск? Он разве не неприменим в описанной выше задаче?

Цитата:

Сообщение от Alexandroppolus
Вполне себе применим.
Найти бинарным поиском первое попавшееся значение, потом от него пробежаться вправо и влево, пособирать все такие же.

Я не вижу тут отсортированного массива.

Nexus 31.10.2020 13:12

Цитата:

Сообщение от Alexandroppolus
Найти бинарным поиском первое попавшееся значение, потом от него пробежаться вправо и влево, пособирать все такие же.

И в чем его преимущество над обычным перебором?

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

Alexandroppolus 31.10.2020 13:32

Цитата:

Сообщение от Nexus
Разве бинарный поиск тут не будет медленнее, чем обычный перебор?

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

Автор не уточнил эти моменты, к сожалению.

voraa 31.10.2020 13:52

Цитата:

Сообщение от Nexus
Разве бинарный поиск тут не будет медленнее, чем обычный перебор?

Если массив отсортирован, то конечно бинарный быстрее.
log2 (N) сравнений.
На 1000 элементов 10 сравнений.
А если неотсортирован, то ничего, кроме перебора не поможет.
Цитата:

Сообщение от Alexandroppolus
А если многократно потребуется искать, то лучше сделать карту.

Отсортировать по возможности.

Nexus 31.10.2020 14:15

Цитата:

Сообщение от Alexandroppolus
Если массив большой и отсортированный

Цитата:

Сообщение от voraa
Если массив отсортирован

ТС привел пример массива. Он, судя по примеру, несортированный.
К тому же имеет, скорее всего, до двух тысяч элементов.

voraa 31.10.2020 15:14

Цитата:

Сообщение от Nexus
К тому же имеет, скорее всего, до двух тысяч элементов.

Ну и какие тут проблемы с перебором?
Я приводил пример - суммирование 10 000 000 элементов массива занимает 20 мс.
https://javascript.ru/forum/530002-post6.html

Nexus 31.10.2020 16:04

Цитата:

Сообщение от voraa
Ну и какие тут проблемы с перебором?

А с чего вы взяли, что я вижу тут какие-то проблемы?

Alexandroppolus 31.10.2020 17:06

Цитата:

Сообщение от voraa
Ну и какие тут проблемы с перебором?

Автор жалуется, что медленно :)
Правда, в его случае используется map, то есть лишние расходы, но тем не менее.

voraa 31.10.2020 18:31

Я даже не представляю, что там может быть долго?
Вот тест.
100 раз выполняется просмотр массива из 10 000 элементов для поиска одинаковых

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-type" content="text/html; charset=utf-8" lang="ru">
  <meta name="viewport" content="width=device-width, initial-scale=1.0" >
  <title>TEST SPEED</title>

<style>
</style>
</head>

<body id="body"  >
<script>
const r = (m) => Math.random()*m | 0;
const colors = ['red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'violet'];
const ar = [];
const l = 10_000;
for (let i = 0; i < l; i++) ar.push ({color: colors[r(colors.length)], data: r(10)});
const nc = 100;

let findsame = (a, key) => {
    const res = [];
    for (let i=0; i<a.length; i++) {
        if (key.color === a[i].color && key.data === a[i].data) res.push(i);        
    }
    return res
}

const t0 = performance.now();
for (ic = 0; ic < nc; ic++) {
    const key = {color: colors[r(colors.length)], data: r(10)};
    const res = findsame(ar, key);
//    console.log(ic, res);
}
const dt = (performance.now()-t0)/1000;

alert(` Time: ${dt} seconds`);
</script>

</body>
</html>


У меня получается 6-8 мс на ноуте (довольно мощный) и 50-60 мс на не слишком навороченном смартфоне.

laimas 31.10.2020 18:53

Цитата:

Сообщение от voraa
Последний раз редактировалось voraa, Сегодня в 18:42.

Еще раз отредактировать, вставлен текст i &lt; l; :)

voraa 31.10.2020 18:56

Цитата:

Сообщение от laimas
Еще раз отредактировать, вставлен текст i &lt; l;

Вот именно это я и редактировал.
Ничего не помогает.
Когда перехожу в режим редактирования там < стоит. Ну меняю < на <. Толку нет.
Но ошибок не выдает и при раскомментаренном console.log(ic, res); результаты выдает, хотя время, конечно, другое.

laimas 31.10.2020 19:14

Нифига себе, происки империалистов, сейчас попробуем. )

var a = b < c;


const r = (m) => Math.random()*m | 0;
const colors = ['red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'violet'];
const ar = [];
const l = 10_000;
for (let i = 0; i < l; i++) ar.push ({color: colors[r(colors.length)], data: r(10)});
const nc = 100;
 
let findsame = (a, key) => {
    const res = [];
    for (let i=0; i<a.length; i++) {
        if (key.color === a[i].color && key.data === a[i].data) res.push(i);       
    }
    return res
}
 
const t0 = performance.now();
for (ic = 0; ic < nc; ic++) {
    const key = {color: colors[r(colors.length)], data: r(10)};
    const res = findsame(ar, key);
//    console.log(ic, res);
}
const dt = (performance.now()-t0)/1000;
 
alert(` Time: ${dt} seconds`);


Нет проблем, скопировал - текст в коде, заменил - все норма. У вас клавиша < на клавиатуре решила, что так лучше будет :)

voraa 31.10.2020 19:27

Цитата:

Сообщение от laimas
У вас клавиша < на клавиатуре решила, что так лучше будет

Причем только 1 раз из трех.
Да хрен с ней лишь бы работало.

Цитата:

Сообщение от laimas
скопировал - текст в коде,

Вот это интересно. Когда я копирую текст из кода, у меня &lt; стоит

laimas 31.10.2020 19:28

Цитата:

Сообщение от voraa
Причем только 1 раз из трех.

Еще и с чувством меры, значит. :)


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