0

actually i'm learning swift with Xcode 11.3.1 to build apps.

I got a question for working with arrays.

I have two arrays and want to combine both by selecting most of values from array one and every nth from array two. Example:

let arr1 = ["Value 1", "Value 2", "Value 3" "Value 4", "Value 5", "Value 6"]
let arr2 = ["Insert 1", "Insert 2", "Insert 3"]

Output should be: Value 1, Value 2, Insert 1, Value 3, Value 4, Insert 2 ...

If arr1 is ended append the last values from arr2 at the end and of course the other way around.

I can put the two arrays together and .shuffle() them but that's not what I finally want.

Hope someone can give a hint or a solution.

PS: In JS I know I can user methods like .reduce and push with using the modulator-operator but this is not JS ;-)

Kind regards, Steven

Joakim Danielson
  • 35,353
  • 5
  • 20
  • 45
  • If you are learning then perhaps you have tried to solve this yourself? Could you share your own code? – Joakim Danielson May 18 '22 at 10:39
  • Not fully tested (edge cases), but https://controlc.com/9ef84575 seems to do the trick with "vintage" for loops... If someone wants to continue on that and check all samples, feel free to use that starting point... – Larme May 18 '22 at 11:02

3 Answers3

1

I would highly recommend using Apple's swift-algorithms package, which makes this really easy.

import Algorithms

let arr1 = ["Value 1", "Value 2", "Value 3", "Value 4", "Value 5", "Value 6"]
let arr2 = ["Insert 1", "Insert 2", "Insert 3"]

result = zip(arr1.chunks(ofCount: 2), arr2.chunks(ofCount: 1)).flatMap(+)
print(result)

Here is it expanded out, to illustrate how this works:

import Algorithms

let arr1 = ["Value 1", "Value 2", "Value 3", "Value 4", "Value 5", "Value 6"]
let arr2 = ["Insert 1", "Insert 2", "Insert 3"]

let arr1Chunks = arr1.chunks(ofCount: 2) // [["Value 1", "Value 2"], ["Value 3", "Value 4"], ["Value 5", "Value 6"]]
let arr2Chunks = arr2.chunks(ofCount: 1) // [["Insert 1"], ["Insert 2"], ["Insert 3"]]

let zipped = zip(arr1.chunks(ofCount: 2), arr2.chunks(ofCount: 1) // [(["Value 1", "Value 2"], ["Insert 1"]), (["Value 3", "Value 4"], ["Insert 2"]), (["Value 5", "Value 6"], ["Insert 3"])

let result = zipped.flatMap { left, right in left + right }

Technically the use of .chunks(ofCount: 1) is a bit unnecessary, but this makes it really easy to tune how many elements of arr2 you want to insert between every chunk of elements of arr1. It could instead be written with:

zip(arr1.chunks(ofCount: 2), arr2).flatMap { $0 + [$1] }

But I find this less clear, tbh.

Alexander
  • 54,014
  • 10
  • 87
  • 136
0

Updated Code : -

I Gave it a try and able to genreate result as below : -

   Result Array = ["Value 1", "Value 2", "Value 3", "Insert 1", "Value 4", "Value 5", "Value 6", "Insert 2", "Value 7", "Value 8", "Value 9", "Insert 3", "Insert 5", "Insert 6"]

The Code I used is as following : -

    let arr1 = ["Value 1", "Value 2", "Value 3", "Value 4", "Value 5", "Value 6", "Value 7", "Value 8", "Value 9"]
    let arr2 = ["Insert 1", "Insert 2", "Insert 3", "Insert 5", "Insert 6"]
    var arrayResult : [String] = []
    let totallength = arr1.count + arr2.count
    let intervalCount = 4
    var count = 0
    for i in 1...totallength {
        if count < arr2.count {

            if i % intervalCount == 0 {
                arrayResult.append(arr2[count])
                count += 1
            } else {
                if i - count - 1 < arr1.count {
                    arrayResult.append(arr1[i - count - 1])
                } else {
                    arrayResult.append(arr2[count])
                    count += 1
                }
            }

        } else {
            arrayResult.append(arr1[i - count - 1])
        }
    }
    print("Result Array = \(arrayResult)")

Hope you found it useful.

Namra Parmar
  • 169
  • 1
  • 5
  • Hi @Namra Parmar, thanks for posting this solution. Work fine so far. A further question: When i change % 3 at the if in the while-loop ... I get an "index out of range error" ... if I append some more data I have to add 2 values and one insert. How to fix that? In mind: maybe there are only 5 values and 3 inserts ... Thanks so far – Steven Woodlink May 18 '22 at 12:26
  • @StevenWoodlink, I have updated code for dynamic values... You can try it and tell me if it does work for you... In this it will append value if any array or interval cross length of any of the array. – Namra Parmar May 19 '22 at 06:06
  • Hi @Namra Parmar first of all, thank you very much. for my test environment this works fine. Now I have added this into my project and have some trouble. I have posted a question here: [link](https://stackoverflow.com/questions/72380386/firebase-to-array-wait-for-all-data-before-do-next-function) Maybe you have an idea how to handle that? Kind regards - Steven – Steven Woodlink May 26 '22 at 03:57
-1

Reduce might be a good option. Just an example from swift, not optimal in performance, but I think it´s readable what it does.

arr2.reduce([]) { partialResult, value in
   partialResult += [wordArray.removeFirst(), wordArray.removeFirst(), value]
}

If you don't want crashed on missing values in arr1

var reversed: [Any] = arr1.reversed()
let combine = arr2.reduce(into: []) { partialResult, value in
partialResult += [reversed.popLast(), reversed.popLast(), value]
}
Mvrp
  • 95
  • 5