#javascript
#javascript
Вопрос:
У меня есть следующий массив :
var selectedRange = [
null,
null,
null,
null,
null,
null,
null,
null,
9, //sequences
10,//sequences
null,
12,
13,
14,
null,
null,
null,
null,
null,
20,
null,
null,
null,
null,
25,
null,
null,
null,
29,
30,
31,
32,
null,
null,
null,
null,
37,
38,
null,
40,
41,
42,
null,
44,
null,
null,
47,
null,
49,
50,
null,
null,
null,
null,
null,
null
]
Мне нужно извлечь последовательности чисел и только чисел, чтобы результат был таким:
["9,10", "12,13,14", "20", "25", "29,30,31,32", "44", "47", "49,50"]
Проблема в том, что я не могу найти решение для извлечения последовательности как есть, я думаю, мне нужна рекурсивная функция, которая повторяет часть проверки, следуют ли последнее число и текущее — как здесь …(!!prm amp;amp; (prm — (index-1)== 1)
let tempArr = [];
$.each(selectedRange, function (index, prm) {
if (!!prm amp;amp; (prm - (index - 1) == 1) {
tempArr.push(prm); // need to loop this section with recursion
}
});
Комментарии:
1. у вас есть первый массив и вам нужен второй или наоборот?
2. @NinaScholz — я обновил вопрос — проверьте его — спасибо
3.
JSON.stringify(selectedRange).match(/([^null, ]) /g)
было бы интересным началом4. можете ли вы работать с массивом массивов вместо того, чтобы помещать последовательности в строку?
5. почему бы просто не отфильтровать нулевые элементы? @mplungjan
Ответ №1:
Один из вариантов — объединить в строку, разделенную запятыми, а затем разделить пустые элементы. Добавьте окончательный фильтр для удаления начальных или конечных пустых элементов. Это может быть не самым эффективным.
var selectedRange = [null, null, null, null, null, null, null, null, 9, 10, null, 12, 13, 14, null, null, null, null, null, 20, null, null, null, null, 25, null, null, null, 29, 30, 31, 32, null, null, null, null, 37, 38, null, 40, 41, 42, null, 44, null, null, 47, null, 49, 50, null, null, null, null, null, null ]
console.log(
selectedRange.join(',').split(/,, |^,|,$/).filter(Boolean)
)
(Отредактировано, чтобы включить комментарии-предложения от @KooiInc и @Ifaruki.)
Комментарии:
1. Не будет работать, если
selectedRange
выглядит так[9, null, null, 10, null, null, 11, ...]
2. @KooiInc почему это не сработает, если входные данные равны [9, null, null, 10, null, null, 11, …]? Когда я пытаюсь это сделать, я получаю [«9», «10», «11»]. Чего вы ожидаете?
3. Попробуйте
console.log([null, 8, null, null, null, 9, 10, null].join(',').split(/,, /).filter((v) => v !== ""));
. Это приведет к:[ ',8', '9,10,' ]
4.
.filter(Boolean)
было бы более элегантным способом, по крайней мере, на мой взгляд5. @KooiInc это отличный момент. Быстрое решение — изменить разделение, что я и сделаю. Хотя, я чувствую, что должен быть более четкий способ выразить это, но это не приходит на ум. Спасибо, что указали на это.
Ответ №2:
Вы можете выполнить итерацию массива и взглянуть на предшественника.
let selectedRange = [null, 8, null, null, null, 9, 10, null],
result = [],
last;
for (const value of selectedRange) {
if (value === null) continue;
if (last 1 === value) result[result.length - 1] = `,${value}`;
else result.push(value.toString());
last = value;
}
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Комментарии:
1. Вам не хватает промежуточных значений в пределах диапазонов
2. Да. Теперь попробуйте с
[null, 8, null, null, null, 9, 10, null]
помощью . Спойлер: приведет к[ '8', '9,10' ]
😉3. плюс 1: вы это исправили; P
Ответ №3:
Вы можете использовать Array.prototype.reduce
для выполнения этой операции следующим образом.
var selectedRange = [ null, null, null, null, null, null, null, null, 9, 10, null, 12, 13, 14, null, null, null, null, null, 20, null, null, null, null, 25, null, null, null, 29, 30, 31, 32, null, null, null, null, 37, 38, null, 40, 41, 42, null, 44, null, null, 47, null, 49, 50, null, null, null, null, null, null ];
let split = null;
const output = selectedRange.reduce((acc, cur) => {
if (cur) {
split ? split = "," cur : split = `${cur}`;
} else {
if (split) {
acc.push(split);
split = null;
}
}
return acc;
}, []);
console.log(output);
сильный текст
Ответ №4:
Вы можете сделать следующее,
var selectedRange = [ null, null, null, null, null, null, null, null, 9, 10, null, 12, 13, 14, null, null, null, null, null, 20, null, null, null, null, 25, null, null, null, 29, 30, 31, 32, null, null, null, null, 37, 38, null, 40, 41, 42, null, 44, null, null, 47, null, 49, 50, null, null, null, null, null, null ];
let isNullSeq = true;
const arr = [];
let temp = '';
selectedRange.forEach((item) => {
if (item) {
if (isNullSeq) {
temp = temp item;
isNullSeq = false;
} else {
temp = ',';
temp = item;
}
} else {
if (!isNullSeq) {
isNullSeq = true;
arr.push(temp);
temp = '';
}
}
});
console.log(arr);
Ответ №5:
Я бы, вероятно, использовал takeWhile
и dropWhile
, вы можете получить их из служебной библиотеки, такой как Ramda, или реализовать их самостоятельно.
const inputs = [
[1,2,null,null,5,6,7,null,null,10,11],
[null,null,3,4,null],
[1,2,null,null,5,null,null],
[null],
[1],
[null, 1],
[],
];
const takeWhile = (predicate) => ([head, ...tail]) => {
if (head === undefined || !predicate (head)) return [];
return [head].concat (takeWhile (predicate) (tail));
}
const dropWhile = (predicate) => ([head, ...tail]) => {
if (head === undefined) return [];
if (!predicate (head)) return [head, ...tail];
return dropWhile (predicate) (tail);
};
const isNull = x => x === null;
const isNotNull = x => x !== null;
const sequence = (list) => {
if (list.length === 0) return [];
if (list[0] === null) return sequence (dropWhile (isNull) (list));
return [takeWhile (isNotNull) (list).join (',')].concat (
sequence (dropWhile (isNotNull) (list))
);
}
console.log (inputs.map (sequence));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Ответ №6:
если у вас есть только нули между ними — как насчет чего-то более простого?
var selectedRange = [ null, null, null, null, null, null, null, null, 9, 10, null, 12, 13, 14, null, null, null, null, null, 20, null, null, null, null, 25, null, null, null, 29, 30, 31, 32, null, null, null, null, 37, 38, null, 40, 41, 42, null, 44, null, null, 47, null, 49, 50, null, null, null, null, null, null]
console.log(selectedRange.toString().replace(/,{2,}/g, ',,').split(",,").filter(function(el) { return el != "";}))
Ответ №7:
Принимая во внимание последовательность, подобную приведенной в вопросе (9, 10, …, — seq = diff of 1
). Следующий код даст требуемый результат —
var selectedRange = [
null,
null,
null,
null,
null,
null,
null,
null,
9, //sequences
10,//sequences
null,
12,
13,
14,
null,
null,
null,
null,
null,
20,
null,
null,
null,
null,
25,
null,
null,
null,
29,
30,
31,
32,
null,
null,
null,
null,
37,
38,
null,
40,
41,
42,
null,
44,
null,
null,
47,
null,
49,
50,
null,
null,
null,
null,
null,
null
]
selectedRange = selectedRange.filter(v => v)
var finalArray = [], temp = [];
for(var i=0; i<selectedRange.length; i )
{
if(selectedRange[i 1]-selectedRange[i] > 1 )
{
temp.push(selectedRange[i]);
finalArray.push(temp.join(","));
temp.length = 0;
}
else temp.push(selectedRange[i])
}
finalArray.push(temp.join(","));
console.log(finalArray);
Ответ №8:
Создайте промежуточный массив массивов последовательностей с использованием Array.reduce
и сопоставьте результирующие последовательности со строками
const selectedRange = [null,null,null,null,null,null,null,null,9, 10,null,12,13,14,null,null,null,null,null,20,null,null,null,null,25,null,null,null,29,30,31,32,null,null,null,null,37,38,null,40,41,42,null,44,null,null,47,null,49,50,null,null,null,null,null,null];
// the reducer lambda
const sequenceReducer = (acc, val) =>
!val ? acc : val - 1 === acc.flat().pop() ?
acc[acc.length-1].push(val) amp;amp; acc : [...acc, [].concat(val)];
console.log( JSON.stringify( selectedRange.reduce(sequenceReducer, []).map( v => v.join() ) ) );
// let's try discontinuous sequences (numbers are not consecutive)
const x = [null, 8, null, null, null, 9, 10, null, 11, null, null, 12, null, 14, null, 15, null, null, 16];
console.log( JSON.stringify( x.reduce(sequenceReducer, []).map( v => v.join() ) ) );
// sequences are discontinuous AND not ordered. Sort first
// (and by the way, note the negative values)
const y = [26, 13, null, 8, null, -3, null, 9, 25, 10, null, 11, null, 7, 12, null, 14, -2, 15, null, 17, 16, -1];
const sortSequenceArray = (a, b) => a - b;
console.log( JSON.stringify( y.sort(sortSequenceArray).reduce(sequenceReducer, []).map( v => v.join() ) ) );