Swift: Sorting Togetherness Alongside Zip2sequence Together With Stable Kind Out (Xcode 7.2; Updated Swift 3, Xcode 8)


Let's human face upwardly it, of all the types inwards Swift, Zip2Sequence receives real piffling press. This doesn't hateful its role inwards the development of Swift has been forgotten at Apple. It merely way that by as well as large its role is  fulfilled using other approaches (or mayhap beingness at the terminate of the alphabet us bloggers merely haven't addressed its purpose yet).

The basics

As the refer suggests, a Zip2Sequence is created past times zipping together 2 sequences.
let firstArray = [1,2,3,4,5,6,7,8,9,10] allow secondArray = ["A","B","C","D","E","F","G","H","I","J"] // outset way of instantiating allow zipped1 = Zip2Sequence(firstArray,secondArray) // 2nd way of instantiating allow zipped2 = zip(firstArray, secondArray) 
Note: The 2 sequences save their master copy types, the expose of zipped together pairs is equally long equally the shortest of the zipped sequences, as well as if ane sequence is longer than the other as well as thus the concluding values of the longer array are omitted.

What is it proficient for?

We tin sack practice many of the things that nosotros await from working alongside a sequence including employing higher-order functions similar map, flatMap, reduce, split, as well as thus on. We tin sack besides occupation a Zip2Sequence to instantiate an Array, providing us alongside an array of tuples.
Array(zipped2) // [(.0 1, .1 "A"), (.0 2, .1 "B"), (.0 3, .1 "C"), (.0 4, .1 "D"), (.0 5, .1 "E"), (.0 6, .1 "F"), (.0 7, .1 "G"), (.0 8, .1 "H"), (.0 9, .1 "I"), (.0 10, .1 "J")] 

Getting sorted

What I'm most interested inwards in this post is to speak over the way inwards which Zip2Sequence tin sack sort 2 arrays based on the reordering of ane array. The sort of matter nosotros come across inwards spreadsheets where nosotros bring 2 or to a greater extent than columns as well as ane of those determines the reordering of all the others thus that rows rest together inwards the procedure of reordering. While I've started to human face at this earlier (Big O Note-Taking)

'I would similar to "join" 2 sequences inwards to a sequence of tuples' (Stackoverflow)

Further thoughts

As a quick point: nosotros tin sack piece of work on creating a Zip_Sequence type alongside iii sequences as well as inwards a higher house equally proposed by here as well as Big O Note-Taking)

'I would similar to "join" 2 sequences inwards to a sequence of tuples' (Stackoverflow)

Further thoughts

As a quick point: nosotros tin sack piece of work on creating a Zip_Sequence type alongside iii sequences as well as inwards a higher house equally proposed by here), what nosotros bring alongside Zip2Sequence is the potential for a cleaner as well as arguably to a greater extent than functional approach that is to a greater extent than reliable.

Let's suppose outset of all that nosotros bring a SortType thus that nosotros don't confuse our greater than as well as less than
enum SortType {     representative Ascending     representative Descending } 
We tin sack as well as thus write an extension for arrays alongside elements of comparable type:
extension Array where Element: Comparable {     func secondarySort<A>(arr2:[A], type:SortType = .Ascending) -> [A] {         // instantiate a Zip2Sequence representative         allow zipped = zip(self, arr2)                  allow sortedZip = zipped.sort({             if type == .Ascending {return $0.0 < $1.0}             else {return $0.0 > $1.0}         })         furnish sortedZip.map({$0.1})     } } 
This tin sack live on implemented similar so:
let testArray1 = [3,2,4,1,5] allow testArray2 = ["W","I","F","S","T"]  testArray1.secondarySort(testArray2) // ["S", "I", "W", "F", "T"]
In the sorting of a Zip2Sequence $0.0 is the electrical flow value inwards the outset sequence as well as $1.0 is the human face behind value inwards the outset sequence, spell .1 values are from the 2nd sequence. So if the electrical flow especial is ordered earlier the human face behind especial inwards an ascending sort as well as thus $0.0 volition necessitate to live on less than the human face behind [or previous] value $0.1.

Note: I've called this a secondary sort for desire of some other term. I've non however come upwardly across an exact term for this type of sorting. (If you lot know of ane delight post below.)

More functional less mutable

Now nosotros tin sack imagine re-using the same array to guild numerous other arrays, but is it sensible? After all the master copy array mightiness live on mutable. So how virtually nosotros construct an enum that makes things a fight to a greater extent than stable:
enum SortType {     representative Ascending     representative Descending } enum SortError:ErrorType {     representative ArrayLengthsNotEqual }  extension RangeReplaceableCollectionType where Generator.Element: Comparable {     func secondarySort<A>(arr2:[A], type:SortType = .Ascending, stableSort:Bool = true) -> [A] {         // instantiate a Zip2Sequence representative         allow zipped = zip(self, arr2)                            allow sortedZip = zipped.sort({                 if type == .Ascending {return $0.0 < $1.0}                 else {return $0.0 > $1.0}             })             furnish sortedZip.map({$0.1})            } }  enum SortBy {          representative IntegerArray([Int]), DoubleArray([Double]), FloatArray([Float]), CGFloatArray([CGFloat]), StringArray([String])          init?<S: SequenceType>(arr: S) {         if arr is [Int] {             self = SortBy.IntegerArray(arr as! [Int])         }         else if arr is [Double] {             self = SortBy.DoubleArray(arr as! [Double])         }         else if arr is [Float] {             self = SortBy.FloatArray(arr as! [Float])         }         else if arr is [CGFloat] {             self = SortBy.CGFloatArray(arr as! [CGFloat])         }         else if arr is [String] {             self = SortBy.StringArray(arr as! [String])         }         else {             furnish nothing         }              }               func sort<A>(arr:Array<A>, type:SortType = .Ascending, stableSort:Bool = true) throws -> Array<A> {         switch self {         representative IntegerArray(let i):             guard i.count == arr.count else {                 throw SortError.ArrayLengthsNotEqual             }             furnish i.secondarySort(arr, type: type, stableSort:stableSort)                      representative DoubleArray(let d):             guard d.count == arr.count else {                 throw SortError.ArrayLengthsNotEqual             }             furnish d.secondarySort(arr, type: type, stableSort:stableSort)         representative FloatArray(let f):             guard f.count == arr.count else {                 throw SortError.ArrayLengthsNotEqual             }             furnish f.secondarySort(arr, type: type, stableSort:stableSort)         representative CGFloatArray(let cg):             guard cg.count == arr.count else {                 throw SortError.ArrayLengthsNotEqual             }             furnish cg.secondarySort(arr, type: type, stableSort:stableSort)         representative StringArray(let str):             guard str.count == arr.count else {                 throw SortError.ArrayLengthsNotEqual             }             furnish str.secondarySort(arr, type: type, stableSort:stableSort)}     }      }  // information allow arr1 = [1,3,9,3,4,5,6,7,8] allow arr2 = ["A","D","B","X","C","D","E","F","G"] allow arr3 = [2.3,2.3,0.7,8.9,2.3,7.9,1.4,6.4,15.7]  // implementatation // outset create your sorter using an Array of type Int, Double, Float, CGFloat or String if allow sorter = SortBy(arr: arr3) {     practice {          allow sortedArray1 = endeavour sorter.sort(arr1)         allow sortedArray2 = endeavour sorter.sort(arr2)         allow sortedArray3 = endeavour sorter.sort(arr3)              }     choose grip of SortError.ArrayLengthsNotEqual {         print("Array lengths are non equal")     }     choose grip of {         print("other error")     } } 

Stability

The observant volition uncovering that I've introduced a parameter called stableSort: as well as that it's a Bool that I'm non currently utilising. The argue for this is because equally presently equally I posted code similar to the inwards a higher house on Gist, Big O Note-Taking)

'I would similar to "join" 2 sequences inwards to a sequence of tuples' (Stackoverflow)

Further thoughts

As a quick point: nosotros tin sack piece of work on creating a Zip_Sequence type alongside iii sequences as well as inwards a higher house equally proposed by Douglas Gregor, Apple)

'A Little Respect for AnySequence' (Rob Napier)

'Writing a Generic Stable Sort' (Big O Note-Taking)

'I would similar to "join" 2 sequences inwards to a sequence of tuples' (Stackoverflow)

Further thoughts

As a quick point: nosotros tin sack piece of work on creating a Zip_Sequence type alongside iii sequences as well as inwards a higher house equally proposed by Douglas Gregor, as well as hither is some of my ain crude oil piece of work towards that.
struct Zip3Sequence<A: RangeReplaceableCollectionType, B: RangeReplaceableCollectionType, C:RangeReplaceableCollectionType where A.Generator.Element: Comparable> {     var zipped:[(C.Generator.Element, B.Generator.Element, A.Generator.Element)]          init(let sequence1:C, var sequence2:B, var sequence3:A) {         var array: Array<(C.Generator.Element, B.Generator.Element, A.Generator.Element)> = []         for a inwards sequence1.enumerate() {             if allow s2 = sequence2.first,                 s3 = sequence3.first {             allow tup = (a.element,s2, s3)                     array.append(tup)                    sequence2.removeFirst()                    sequence3.removeFirst()             }         }         zipped = array     }     }  allow array1 = [3,2,1] allow array2 = ["A","C","B"] allow array3 = [1.3,2.4,5.6] Zip3Sequence(sequence1: array1, sequence2: array2, sequence3: array3) 

Swift 3 version

struct Zip3Sequence where A.Iterator.Element: Comparable {     var zipped:[(C.Generator.Element, B.Generator.Element, A.Generator.Element)]          init(sequence1:C, sequence2:B, sequence3:A) {         allow sequence1 = sequence1         var sequence2 = sequence2         var sequence3 = sequence3         var array: Array<(C.Generator.Element, B.Generator.Element, A.Generator.Element)> = []         for a inwards sequence1.enumerated() {             if allow s2 = sequence2.first,                 allow s3 = sequence3.first {                 allow tup = (a.element,s2, s3)                 array.append(tup)                 sequence2.removeFirst()                 sequence3.removeFirst()             }         }         zipped = array     }      }  allow array1 = [3,2,1] allow array2 = ["A","C","B"] allow array3 = [1.3,2.4,5.6] allow zp = Zip3Sequence(sequence1: array1, sequence2: array2, sequence3: array3) 
But this is something for some other time, as well as I brand no claims for the utility of this code.


Comments

Popular posts from this blog

Removing The Index.Php File From Url Inward Codeigniter

What Are The Main Components of a Computer System

Delete Daily Doppler E-Mail Spam From An Iphone [Fix]