#javascript #google-apps-script #google-sheets
Вопрос:
У меня есть множество дат. У меня есть конкретная дата «Дата поиска». Я хочу найти дату в массиве, которая ближе всего к Дате поиска, но меньше, чем дата поиска, и вернуть индекс этой даты в массиве.
Пример: Предположим , что массив дат [8/1/21, 8/5/22, 8/5/23]
проиндексирован 1,2,3
для примера. Предположим, что моя дата поиска такова 9/17/22
. Функция должна найти дату 8/5/22
и вернуть индекс 2
.
В Google Таблицах это просто функция сопоставления:
Как это сделать (и наиболее эффективно) в сценарии приложений? IndexOf()
Функция, похоже, возвращает только точное совпадение, которое в данном случае не работает.
Спасибо!
Ответ №1:
Объяснение:
Идея состояла бы в том, чтобы сравнить каждую дату в массиве с датой поиска и выбрать абсолютную минимальную разницу, которая будет ближайшей датой к дате поиска:
const checkDif = checkDates.map(d=>searchDate - d).filter(v=>v>0);
const minIndex = checkDif.indexOf(Math.min(...checkDif)) 1;
- карта используется для вычисления разницы между датами для каждой даты во входном массиве.
- фильтр используется для выбора только положительных различий (а именно дат, которые меньше даты поиска).
- Математич.мин используется для вычисления минимального значения массива положительных разностей, следовательно, ближайшая дата, которая меньше даты поиска.
- indexOf используется для вычисления индекса этого минимального значения.
Мы делаем 1
это, потому что индексы массива JavaScript
начинаются с 0
, но, похоже, вы хотите, чтобы они начинались с 1
.
Решение:
Дополнительные пояснения см. в комментариях, а также в случае, если вы хотите изменить диапазоны или название листа.
function closestDate() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet1"); // name of the sheet
const searchDate = sh.getRange("B4").getValue(); // search date
const checkDates = sh.getRange("B1:D1").getValues().flat(); // input range
const checkDif = checkDates.map(d=>searchDate - d).filter(v=>v>0);
const minIndex = checkDif.indexOf(Math.min(...checkDif)) 1;
console.log(minIndex); // 2
sh.getRange("B5").setValue(minIndex); // return the result to B5
}
Пример, который работает с фрагментом кода:
Комментарии:
1. Это так невероятно полезно. Спасибо. Ваш код и объяснение удивительны. У меня есть один последующий вопрос. Моя цель-получить индекс исходного массива дат. Ваш код, приведенный выше, работает, потому что я перечислил даты в порядке возрастания, от самой старой до самой новой даты. Однако, если даты в массиве были расположены в случайном порядке, указанный вами код даст индекс отфильтрованного массива положительных значений. Поэтому, если даты не в порядке, это будет неправильный индекс. Видите ли вы способ изменить то, что вы написали, чтобы получить минимальное положительное значение вашего
checkDif
массива?2. @КимХопкинс, порядок дат не имеет значения. Код сравнивает различия, а затем находит минимальное положительное значение. Позиция на этом шаге не имеет значения, поскольку индекс рассчитывается методом indexof. Так что порядок не имеет значения. Если вы считаете иначе, отредактируйте свой вопрос и включите пример, который, по вашему мнению, не работает. Также подумайте о том, чтобы принять и проголосовать за ответ, когда он решит проблему
3. ОК. Я подумал, что, поскольку код отфильтрован на наличие положительных различий, этот фильтр создаст новый массив, и поэтому индекс будет соответствовать новому массиву по сравнению с исходным массивом. В случае, например, если даты были в обратном хронологическом порядке, я думал, что из-за этого он вернет неправильный индекс. Еще раз спасибо вам. Я не могу озвучивать, потому что я новичок, но я очень признателен вам за ваш отчет.