2017-07-06 8 views
0

タプル(Int、CustomType、OtherCustomType)の配列を持っています。配列は、タプルのInt部分でソートされます。swift - タプルの配列内の単一タプルアイテムを繰り返します。

正しい位置に新しい要素を追加するために、バイナリ検索機能を使用して挿入ポイントのインデックスを取得しました。

この関数は、新しい要素(Int、Bool)を返します.Boolは要素が既に存在するかどうかを示し、Intは新しい要素の最初の出現のインデックスか、または最初の要素のインデックスです新しい要素よりも大きい。

機能がジェネリック書かれている、それは明らかに、私は単にタプルの私の配列を渡すことができない、同等のタイプと引数と同じ型の新しい要素の配列を受け取り、そう。

簡単な解決策はこれに代えて1つのアレイ内のタプルが、私は3つの別々の配列、唯一3つの値のそれぞれを使用することができるように3つの値を記憶する、私のデータを再編成することであろう。次に、最初の配列だけをバイナリ検索関数に渡して、見つかったインデックスの3つの配列すべてに対して目的のアクションを実行します。

しかし、タプルとして組織の私のデータを保持し、我々のような比較でタプルの部分を無視することができますように、関数に各タプルの一つだけの要素を渡す方法があり、「もしタプル==(_、23 、_) "?

EDIT:サンプルコード:

func findInsertPoint <T: Comparable> (forElement: T, inArray: [T]) -> (Int, Bool) { 
    var low = 0 
    var high = inArray.count 

    if forElement > inArray[high-1] { 
     return (high, false) 
    } 
    while low < high { 
     let mid = (low+high)/2 
     if inArray[mid] >= forElement { 
      high = mid 
     } else { 
      low = mid+1 
     } 
    } 
    return(low,(inArray[low] == forElement)) 
} 

intの配列が完全に正常に動作します:

// index   0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
var testArray = [1,2,5,7,8,11,12,12,12,15,19,22,22,26,52,56] 

findInsertPoint(forElement: x, inArray: testArray) 

// x = 17 returns (10,false) 
// x = 19 returns (10,true) 

しかし、私の実際の配列は、このようなものになります。

var testArray = [(4,"Bee",2.5),(5,"dog",1.0),(8,"dog",43.13)] 

を私は探しています各タプルの最初の部分だけの配列を渡す方法はありますが、実際の高価な作成はありません各関数呼び出しの新しい配列。

ので、可能性は完璧になる...このような機能...

findInsertPoint(forElement: 7 in Array: testArray.0) 

呼び出すことが、私は、これは動作しません知っています。

ので、TL; DR:一時的にタプルのみの単一型の配列を受け入れる関数呼び出しのための構造体のメンバーを無視する迅速な方法はありますか?

はない場合、私は二つの可能性が知っている:私のtayloredバイナリ検索(上記のコードからではない、一般的なもの)

  • 除算3つの別々のアレイにタプルに

    1. スティック。
  • +0

    通常のアプローチは、例えばのように、カスタムの比較関数を渡すことですここ:https://stackoverflow.com/a/26679191/1187415、https://developer.apple.com/documentation/swift/array/2296815-sortedのような既存のソートメソッドと同様です。 –

    +0

    "私は3つの別々の配列を使うことができました。各配列は3つの値のうちの1つだけです。"最も確かにこれをしないでください。そういうわけで、狂気がある。 – Alexander

    +0

    これを実行するためのコンパイル可能なサンプルデータを教えていただけますか? – Alexander

    答えて

    2

    これは私が見つけた解決策である:

    あなたが自分でコレクション型です型の配列を持っており、あなただけの外側の配列の各メンバーの特定のプロパティを見てみたい、使用している場合swiftのコレクション型の.mapメソッド:

    var testArray = [(4,"Bee",2.5),(5,"dog",1.0),(8,"dog",43.13)] 
    var onlyFirstProperty = testArray.map({$0.0}) // [4,5,8] 
    

    このようにして、各タプルの最初の要素のみからなる新しい配列を取得します。 $ 0.0は、firstMember.firstPropertyの簡略構文です。私のコードでは、私はこのように私の関数を呼び出すことができます。

    findInsertPoint(forElement: 7 in Array: testArray.map({$0.0})) 
    
    +0

    誰かが.mapメソッドがどれほど高価であるかを伝えることができますか?このようなマップを関数パラメータとして使用すると、実際に新しい配列を作成するか、または新しい配列のメンバーが元の配列への参照になりますか?あるいは、値の型が適用されているときに、少なくともコピーオンライトの動作を迅速にするでしょうか? – MassMover

    0

    あなたは構造体を作成し、そのようにそれに匹敵するプロトコルを実装することができます:

    を:この構造により

    struct Foo: Comparable { 
        let a: Int 
        let b: TypeB 
        let c: TypeC 
    
        // compare according to the integers 
        static func ==(lhs: Foo, rhs: Foo) -> Bool { 
         return lhs.a == rhs.a 
        } 
    
        static func <(lhs: Foo, rhs: Foo) -> Bool { 
         return lhs.a < rhs.a 
        } 
    } 
    

    を次のように、あなたは、所望の結果をカスタム汎用のソート関数を呼び出すことができます

    let foos = [Foo]() 
    let (position, exists) = customSort(foos) 
    

    カスタムソート関数は、同等のプロトコルを使用しているので、構造体とうまく動作するはずです。

    +0

    私は最後のこのコードの一部ですが、それを匹敵する構造体にすることは、私がまだ考えていた解決策です。私は、さらなる発展の中で、所与の価値の指標をどこで見つけなければならないのかを分類する以外の可能性のある状況があると信じる理由があります。 – MassMover

    +0

    @MassMover与えられた値のインデックスを見つけることによって、Intを与えられたことを意味しますか、同じint値を持つタプルを見つけますか? 'foos.filter({$ 0.a == x}) 'を使って簡単に実現できます。' x'は興味のあるint値です。 – mohak

    +0

    これは実際には一致する要素の配列を要素のインデックスではなく、要素のみを返します。しかし、より高次の関数.map、.filter。私の質問をするときに私には分かっていなかった.reduceは確かに正しい場所でした。 – MassMover

    関連する問題