Javascript выбирает номера пиков из групп максимумов в массиве - PullRequest
0 голосов
/ 13 июня 2019

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

Так, например, вэтот массив:

const arr = [939, 1301, 253, 1380, 1037, 2279, 2462, 2193, 2121, 1424, 506, 2411, 2456, 2295, 915, 1276, 1532, 1359, 985, 2182, 2407, 2103, 2392, 2294, 765, 1195, 1537, 1409, 858, 1971, 2214, 1311, 1326, 1383, 1231, 1141]

Я хочу выбрать 2462 из первой группы пиков примерно на 1037, 2279, 2462, 2193, а затем перейти к выбору 2456 из следующей группы на отметке 506, 2411, 2456, 2295, 915,Местоположения групп неизвестны, вопрос в том, чтобы найти их и выбрать одно наибольшее число из каждой группы.

Это функция, которая у меня есть в данный момент, но она не работает на 100% и не работает.не работают с определенными массивами.

let currHigh = 0, store = [], limit = 2100;
for (let s = 0; s < arr.length; s++) {
    if (arr[s] > limit && currHigh === 0) {
        currHigh = arr[s]
    } else if (arr[s] > limit && arr[s] > currHigh) {
        currHigh = arr[s];
    } else if (arr[s] < currHigh) {
        if (arr[s] < limit) {
            store.push(currHigh); currHigh = 0;
        }
    }
}
console.log(store)

Максимумы всегда очень похожи (2000+), а расположение групп чисел схоже, но не одинаково, поэтому я не могу на это полагаться.

Таким образом, первый массив и ожидаемый / желаемый вывод будут:

const arr = [939, 1301, 253, 1380, 1037, 2279, 2462, 2193, 2121, 1424, 506, 2411, 2456, 2295, 915, 1276, 1532, 1359, 985, 2182, 2407, 2103, 2392, 2294, 765, 1195, 1537, 1409, 858, 1971, 2214, 1311, 1326, 1383, 1231, 1141]

Outputted Peaks: [2462, 2456, 2407, 2294, 2214]

И еще один пример массива с ожидаемым / желаемым выводом:

const arr =  [1365, 1324, 1013, 1220, 1259, 2204, 2212, 1938, 1882, 1545, 1236, 2090, 2614, 1949, 1307, 1628, 1780, 1263, 1184, 2184, 1411, 1306, 2010, 2057, 1339, 1624, 2480, 2575, 2425, 2617, 2479, 1929, 1805, 1869, 1341, 1104, 2195, 1661, 1174, 1447, 1761, 1362, 1430]

Outputted Peaks: [2212, 2614, 2184, 2480, 2617, 2195]

РЕДАКТИРОВАТЬ: чтобы сохранить некоторыепутаница, представьте, что если вы возьмете значения в заданном массиве и нанесете их на график, на графике будет несколько пиков, разнесенных друг от друга.Мне нужна функция, которая получает эти пики.Поиск групп - это только один из способов найти вершины.Они были бы как мини горы.Таким образом, вы не хотели бы получать большое число, например, на «стороне горы».

РЕДАКТИРОВАТЬ: Прикрепление изображения для объяснения пиков.Старшее число рядом с другим старшим числом не является пиком, только самое большое число в небольшой группе соседних чисел является пиком.enter image description here

Окончательное РЕДАКТИРОВАНИЕ: Этот график лучше всего иллюстрирует это, поскольку трудно представить график, просто смотрящий на массив:

https://jsbin.com/nicuciquru/1/edit?js,output

Здесь мне нужны пики [1301, 1380, 2462, 2456, 1532, 2407, 2492, 1537, 2214, 1383], которые вы можете увидеть на графике.Затем оттуда эти пики могут легко фильтроваться с пороговым значением, например, для устранения любых пиков ниже 2000.

Ответы [ 4 ]

1 голос
/ 13 июня 2019

Вот функция, которая находит все пики в вашем массиве выборок:

    const chart = [939, 1301, 253, 1380, 1037, 2279, 2462, 2193, 2121, 1424, 506, 2411, 2456, 2295, 915, 1276, 1532, 1359, 985, 2182, 2407, 2103, 2392, 2294, 765, 1195, 1537, 1409, 858, 1971, 2214, 1311, 1326, 1383, 1231, 1141]

    const findPeaks = chart => chart.reduce((agg, current, i) => {
        const prev = chart[i - 1];
        const next = chart[i + 1];

        return current > prev && current > next ? [...agg, current] : agg;
    }, []);

    const peaks = findPeaks(chart);

    console.log('peaks', peaks);

Эти журналы: [1301, 1380, 2462, 2456, 1532, 2407, 2392, 1537, 2214, 1383]

Это не соответствует ожидаемому результату вашего вопроса, но дает точный ответ на вопрос "каковы пики".

В этом случае «пик» определяется как любое число, предшественник и преемник которого меньше, чем он сам. то есть [1, 100, 1] дает 100. [1, 2, 3, 100, 3, 2, 100, 1] дает [100, 100]

Обновление

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

const findPeaks = chart => chart.reduce((agg, current, i) => {
        const twoBack = chart[i - 2];
        const prev = chart[i - 1];
        const next = chart[i + 1];
        const twoForward = chart[i + 2];

        return (twoBack < prev && prev < current) && (current > next  && next > twoForward ) 
        ? [...agg, current] 
        : agg;
    }, []);

Для приведенного выше ввода получается:

[2462, 2456, 1532, 1537, 1383]

Обновление 2

Вот версия кода, которая находит все пики, вычисляет медиану и возвращает все пики, превышающие медиану. Это самый близкий результат к тому, что вы просите в своем вопросе:

const findPeaks = chart => {

    const peaks = chart.reduce((agg, current, i) => {
    const twoBack = chart[i - 2];
    const prev = chart[i - 1];
    const next = chart[i + 1];
    const twoForward = chart[i + 2];

    return (prev < current) && (current > next) 
    ? [...agg, current] 
    : agg;
    }, []);

    const mean = peaks.reduce((a, b) => a + b) / peaks.length;

    return peaks.filter(peak => peak > mean);
}

Вывод этого:

[2462, 2456, 2407, 2392, 2214]

0 голосов
/ 13 июня 2019

почему бы не сделать это простым?

var arr = [1,6,4,3,9,11];

var peaks = arr.sort((a, b) => a - b).reverse();

вывод: [11, 9, 6, 4, 3, 1]

, то:

var top5 = peaks.slice(0,5);

и результат: [11, 9, 6, 4, 3]

или весь код вашего матери:

const peaks1 = [939, 1301, 253, 1380, 1037, 2279, 2462, 2193, 2121, 1424, 506, 2411, 2456, 2295, 915, 1276, 1532, 1359, 985, 2182, 2407, 2103, 2392, 2294, 765, 1195, 1537, 1409, 858, 1971, 2214, 1311, 1326, 1383, 1231, 1141];
const peaks2 =  [1365, 1324, 1013, 1220, 1259, 2204, 2212, 1938, 1882, 1545, 1236, 2090, 2614, 1949, 1307, 1628, 1780, 1263, 1184, 2184, 1411, 1306, 2010, 2057, 1339, 1624, 2480, 2575, 2425, 2617, 2479, 1929, 1805, 1869, 1341, 1104, 2195, 1661, 1174, 1447, 1761, 1362, 1430];
const peaks = [peaks1, peaks2];
function getPeaks(arr){
    let peaks = [];
    for(let i=0;i<arr.length;i++){
        let currPeak = arr[i].sort((a, b) => a - b).reverse().slice(0,1)[0];
        peaks.push(currPeak);
    }
    return peaks.sort((a, b) => a - b).reverse();
}
let result = getPeaks(peaks);

и результатом будет: [2617, 2462]

0 голосов
/ 13 июня 2019

Исходя из всего, что мы обсуждали, и я вижу из ваших комментариев, я думаю, что следующее должно сработать для вас.По сути, просто перебираем точки и проверяем, больше ли текущая точка, чем предыдущая и следующая точки - мы можем считать эти точки «пиками»:

function getPeaks(points) {
  let prev;
  let next;
  return points.filter((curr, idx, arr) => {
    if (idx > 0) {
      prev = arr[idx - 1];
    }
    if (idx < (arr.length - 1)) {
      next = arr[idx + 1];
    }

    if (prev) {
      if (prev > curr) {
        return false;
      }
    }
    if (next) {
      if (next > curr) {
        return false;
      }
    }

    return true;
  });
}
const points = [939, 1301, 253, 1380, 1037, 2279, 2462, 2193, 2121, 1424, 506, 2411, 2456, 2295, 915, 1276, 1532, 1359, 985, 2182, 2407, 2103, 2392, 2294, 765, 1195, 1537, 1409, 858, 1971, 2214, 1311, 1326, 1383, 1231, 1141];

console.log(getPeaks(points));

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

0 голосов
/ 13 июня 2019

Без более точного определения желаемого результата (например, что считается группой?) Приведем упрощенный алгоритм:

1) разбить массив на последовательности «low» и «high».

  • Например, [1, 10000, 100, 101, 20000, 20050, 30, 10, 2] => [1], [10000], [100, 101], [20000, 20050], [30, 10, 2].

2) Возвращает максимум каждой старшей последовательности.

let peaks = arr => {
	let isHigh = a => a >= 2000;
	let isLow = a => !isHigh(a);

	let groups = [];
	while (arr.length && arr.some(isHigh)) {
		arr.splice(0, arr.findIndex(isHigh));
		groups.push(arr.splice(0, arr.findIndex(isLow)));
	}

	return groups.map(group => Math.max(...group));
};


const arr = [939, 1301, 253, 1380, 1037, 2279, 2462, 2193, 2121, 1424, 506, 2411, 2456, 2295, 915, 1276, 1532, 1359, 985, 2182, 2407, 2103, 2392, 2294, 765, 1195, 1537, 1409, 858, 1971, 2214, 1311, 1326, 1383, 1231, 1141];
console.log(peaks(arr));

const arr2 = [1365, 1324, 1013, 1220, 1259, 2204, 2212, 1938, 1882, 1545, 1236, 2090, 2614, 1949, 1307, 1628, 1780, 1263, 1184, 2184, 1411, 1306, 2010, 2057, 1339, 1624, 2480, 2575, 2425, 2617, 2479, 1929, 1805, 1869, 1341, 1104, 2195, 1661, 1174, 1447, 1761, 1362, 1430];
console.log(peaks(arr2));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...