Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
685 views
in Technique[技术] by (71.8m points)

arrays - In Swift I would like to "join" two sequences in to a sequence of tuples

I would like to join two (or more) sequences that would then create a sequence of tuples. Where the first tuple would contain the first element of each sequence and the second tuple would contain the second elements, etc ... Below is an example function that takes two arrays and creates a third array of tuples. I then can use this sequence to process with map(), filter() and reduce() functions.

My example works, but is lacking in a bunch of ways. It is for arrays not for all sequences, It stops generating tuples when the first sequence runs out of elements. I would like nils to be in the tuples for the short sequences that can no longer provide elements. It is only for two arrays, I would like it to be for any number of sequences,

Partial solutions would be helpful. I'm a functional programming newbie so the proper name for this function would also be appreciated. Maybe its is already in the switfz library I just know what it is called. I chose "join" because it is roughly similar to the SQL "join" which also builds tuples (a.k.a. rows)

func join<T> (s1: Array<T>, s2: Array<T>) -> Array<(T,T)> {

var g1 = s1.generate();
var g2 = s2.generate();

var result:Array<(T,T)> = []

while let e1 = g1.next() {

    if let e2 = g2.next() {
        result.append((e1,e2))
    }
}
return result
}


class Hamming {
    class func compute(input: String, against: String) -> Int {
        return join(Array(input),Array(against)).reduce(0){ return ($1.0 != $1.1) ? $0 + 1 : $0 }
    }
}

Hamming.compute("abcde","abcdf")  // 1
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There is already a function for that called Zip2:

var first = [0,1,2,3]
var second = ["zero", "one", "two", "three"]

Array(Zip2(first,second))
// (0, "zero"), (1, "one"), (2, "two"), (3, "three")

This function however does not pad with nil and it also uses the shortest of the two passed in sequences. Notice though that it does not require that the types match between the two sequences and that it takes any sequence, not just arrays.

Here is my own custom implementation of Zip2WithNilPadding:

struct Zip2WithNilPadding<T: SequenceType,U: SequenceType>: SequenceType {
    typealias Generator = GeneratorOf<(T.Generator.Element?, U.Generator.Element?)>

    let first: T
    let second: U

    init(_ first: T, _ second: U) {
        self.first = first
        self.second = second
    }

    func generate() -> Generator {
        var generator1: T.Generator? = first.generate()
        var generator2: U.Generator? = second.generate()

        return GeneratorOf<(T.Generator.Element?, U.Generator.Element?)>() {
            let element1 = generator1?.next()
            let element2 = generator2?.next()
            if element1 == nil && element2 == nil {
                return nil
            }
            else if element1 == nil{
                generator1 = nil
            }
            else if element2 == nil {
                generator2 = nil
            }
            return (element1, element2)
        }
    }
}

var first = [0,1,2]
var second = ["zero", "one", "two", "three", "four"]
Array(Zip2WithNilPadding(first, second))

If you have questions about the specific implementation let me know and I will try to clarify. This implementation should also help you in creating a Zip that takes an array of sequences. Unfortunately in that case they would all have to be a sequence of the same type because you can't have a variable amount of generics.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...