Массив целых чисел в массивы диапазонов - PullRequest
0 голосов
/ 31 мая 2019

Моя задача: Мне нужно разделить массив на несколько массивов массивов со следующими свойствами:

  1. каждый подмассив представляет собой диапазон непрерывного целого числа.Например, [1,2,3,4,5] будет [[1,5]].

  2. Когда нет смежных целых чисел, создайте новый подмассив.Например, [1,2,4,5] будет [[1,2], [4,5]]

Пример:

Если у меня есть этот массив целых чисел - [0, 1, 5, 6, 3, 7]

Ожидаемый результат - [[0, 1], [3], [5, 7]]

Я уже пробовал это:

let array: [Int] = [0, 1, 3, 4, 5, 6, 7]

var group: [[Int]] = []
var temp: [Int] = [Int]()

for (index, element) in array.enumerated() {
    if index + 1 < array.count {
        let nextElement = array[index + 1]
        let step = nextElement - element

//        temp.append(element)

        if(step) == 1 { // Until it's in range
            temp.append(element)
        } else { // One-by-one
            temp.append(element)
            group.append(temp)

            temp = [Int]()
            group.append([nextElement])
        }
    } else {
        print(index)
    }
}

print(group)

Из моего кода я получаю этот результат - [[0, 1], [3]]

Ответы [ 3 ]

2 голосов
/ 31 мая 2019

Есть API, IndexSet :

Непонятно, что вы хотите, ваши примеры неоднозначны.

Если вам нужен массив диапазонов

let indexSet = IndexSet(array)
let rangeView = indexSet.rangeView
let group = rangeView.map { $0.indices.startIndex..<$0.indices.endIndex }

Если вы хотите сгруппировать массив по диапазонам

let indexSet = IndexSet(array)
let rangeView = indexSet.rangeView
let group = rangeView.map { Array($0.indices) }
0 голосов
/ 31 мая 2019

Вот мое решение. Вместо того, чтобы вручную управлять индексами, я использую два итератора. Тот, который продвигается вперед, обозначая «начало» прогонов, и тот, который мчится вперед, чтобы найти «концы» трасс.

Я усовершенствовал мой код для работы с любым Sequence (не только Array) и любым типом Strideable (любым типом, который определяет distance(to:), не обязательно просто Int).

extension Sequence where Element: Strideable {
    func splitConsequtiveRuns() -> [[Element]] {
        var runs = [[Element]]()

        var runStartIterator = self.makeIterator()

        while let startElement = runStartIterator.next() {
            var runEndIterator = runStartIterator
            var prevElement = startElement

            var run = [startElement]
            while let nextElement = runEndIterator.next(),
                prevElement.distance(to: nextElement) == 1 {
                _ = runStartIterator.next() // advance the "start" iterator, to keep pace

                prevElement = nextElement // update this, for use in then next loop's comparison
                run.append(nextElement)
            }

            runs.append(run)
        }

        return runs
    }
}

let array: [Int] = [0...3, 8...8, 10...15].flatMap { $0 }
print(array.splitConsequtiveRuns()) // => [[0, 1, 2, 3], [8], [10, 11, 12, 13, 14, 15]]
0 голосов
/ 31 мая 2019

Это лучший подход, который я нашел:

let array: [Int] = [0, 1, 5, 6, 3, 7].sorted();

var group: [[Int]] = []
var temp: [Int] = [Int]()
var lastElement: Int = -1;
for (index, element) in array.enumerated() {
    if lastElement == -1 {
      temp.append(element);
    }
    else {
      if element - lastElement == 1 {
        temp.append(element);
      }
      else {
        group.append(temp);
        temp = [Int]();
        temp.append(element);
      }
    }
    lastElement = element;
}
if temp.count > 0 {
  group.append(temp);
}

print(group)
...