Как получить буквально одинаковый размер массива в Swift - PullRequest
0 голосов
/ 10 ноября 2019

Например, с массивом let array = [1, 3, -5, 2, 6], я хочу получить этот вывод: с равным размером (N) среза массива.

, если N = 2, то вывести: [1,3] [3,-5] [-5,2] [2,6]

если N = 3, то выведите: [1,3,-5] [3,-5,2] [-5,2,6]

/ / / Обновите мой код, как показано ниже, winSize использует для определения размера массива срезов, полученного из readLine ()

class windowSize {
    var resultArray = [Int]()

    func execTest() {
        print("please give the window size W and length(S) of array, seperated by space")
        if let firstLine = readLine() {
            let firstLineArray = firstLine.compactMap{Int(String($0))}
            let winSize = firstLineArray[0]

            print("please give the test array with S length")
            if let arr1 = readLine() {
                let arr = arr1.compactMap{Int(String($0))}
                // print(arr)

                // get each slice array with window size length
                let slicedArray = arr.neighbors

                // get max value in each slice array
                for ele in slicedArray {
                    let max = ele.max()
                    resultArray.append(max!)
                }

                print("resultarray", resultArray)
            }
        }
    }
}

extension Collection {
    var neighbors: [SubSequence] {
        guard !isEmpty else { return [] }
        return indices.dropLast().map {
            return self[$0..<(index($0, offsetBy: 2, limitedBy: self.endIndex) ?? self.endIndex)]
        }
    }
}

windowSize().execTest()

Ответы [ 2 ]

2 голосов
/ 10 ноября 2019

Вы можете перебирать индексы своей коллекции, отбрасывая последний и возвращая каждый элемент вместе с его последующим соседом:

extension Collection {
    var neighbors: [SubSequence] {
        indices.dropLast().map {
            self[$0..<(index($0, offsetBy: 2, limitedBy: self.endIndex) ?? self.endIndex)]
        }
    }
}

let array = [1, 3, -5, 2, 6]
let chunks = array.neighbors  // [[1, 3], [3, -5], [-5, 2], [2, 6]]
let maxValues = chunks.compactMap{$0.max()}  // [3, 3, 2, 6]

Если вам нужно более двух элементов:

extension Collection {
    func customChunk(of n: Int) -> [SubSequence] {
        indices.dropLast(n-1).map {
            self[$0..<(index($0, offsetBy: n, limitedBy: self.endIndex) ?? self.endIndex)]
        }
    }
}

let chunks3 = array.customChunk(of: 3)  // [[1, 3, -5], [3, -5, 2], [-5, 2, 6]]
let maxValues3 = chunks.compactMap{$0.max()}  // [3, 3, 6]
0 голосов
/ 10 ноября 2019

Вот простое решение:

func windows<T>(in a: [T], ofSize w: Int) -> [[T]] {
    //You could decide here what you want to return if w is invalid
    if w > a.count || w <= 0 {
        return []
    }

    var output = [[T]]()
    for i in 0..<a.count-w+1 {
        output.append(Array(a[i..<i+w]))
    }
    return output
}

И вот несколько вариантов использования:

windows(in: [1, 3, -5, 2, 6], ofSize: 2) //[[1, 3], [3, -5], [-5, 2], [2, 6]]
windows(in: [1, 3, -5, 2, 6], ofSize: 3) //[[1, 3, -5], [3, -5, 2], [-5, 2, 6]]

Максимум скользящего окна

Расчет скользящего окнаМаксимум при первом создании всех подмассивов расточителен:

let ws = windows(in: [1, 3, -5, 2, 6], ofSize: 3)
let maxs = ws.compactMap { $0.max() } //[3, 3, 6]

Ниже вы можете найти несколько лучших решений:

Подход 1:

Вот два подхода к вычислениюКлассическое раздвижное окно Максимум:

func slidingWindowMax(_ a: [Int], _ w: Int) -> [Int] {
    let n = a.count

    if n < 2 || w == 1  {
        return a
    }

    var maxLeft = Array(repeating: 0, count: n)
    var maxRight = Array(repeating: 0, count: n)

    maxLeft[0] = a[0]
    maxRight[n - 1] = a[n - 1]

    for i in 1..<n {
        maxLeft[i] = i % w == 0 ? a[i] : max(maxLeft[i - 1], a[i])

        let j = n - i - 1
        maxRight[j] = j % w == 0 ? a[j] : max(maxRight[j + 1], a[j])
    }

    var slidingWindowMax = Array(repeating: 0, count: n - w + 1)

    var k = 0

    for i in 0 ..< n - w + 1 {
        slidingWindowMax[k] = max(maxRight[i], maxLeft[i + w - 1])
        k += 1
    }

    return slidingWindowMax
}

Подход 2:

func slidingWindowMax2(_ array: [Int], _ window: Int) -> [Int]{

    let n = array.count

    if n < 2 || window == 1 {
        return array
    }

    var result = Array(repeating: 0, count: n - window + 1)
    var maxIndex = -1, maximum = Int.max

    for start in 0 ..< n - window + 1 {
        let end = start + window - 1
        if maxIndex < start {
            maxIndex = start
            maximum = array[start]
            for next in start + 1 ... end {
                if array[next] > maximum {
                    maxIndex = next
                    maximum = array[next]
                }
            }
        } else {
            if array[end] > maximum {
                maxIndex = end;
                maximum = array[end]
            }
        }
        result[start] = maximum
    }
    return result
}
...