2017-01-06 7 views
1

私はSwift(iOS)にJava(Android)で使用していたアルゴリズムを移植しており、Swiftバージョンの速度に関するいくつかの問題を抱えています。アレイに遅すぎるスウィフトが含まれています

深みのあるオブジェクト(コメントツリー)があり、非表示のオブジェクトのリストと照合してデータセットからの返信を非表示にすることができます。以下は、可視化

Top 
- Reply 1 
- - Reply 2 
- - Reply 3 
- Reply 4 

であり、データセットから、私は、Javaから変換されてきた

Top 
- Reply 1 
- Reply 4 

関連するメソッドを非表示にした後

//Gets the "real" position of the index provided in the "position" variable. The comments array contains all the used data, and the hidden array is an array of strings that represent items in the dataset that should be skipped over. 

    func getRealPosition(position: Int)-> Int{ 

     let hElements = getHiddenCountUpTo(location: position) 
     var diff = 0 
     var i = 0 
     while i < hElements { 
      diff += 1 
      if(comments.count > position + diff && hidden.contains(comments[(position + diff)].getId())){ 
       i -= 1 
      } 
      i += 1 
     } 
     return position + diff 
    } 

    func getHiddenCountUpTo(location: Int) -> Int{ 
     var count = 0 
     var i = 0 
     repeat { 
      if (comments.count > i && hidden.contains(comments[i].getId())) { 
       count += 1 
      } 
      i += 1 
     } while(i <= location && i < comments.count) 
     return count 
    } 

これはのUITableViewControllerにして使用されている以下の通りです。コメントをツリーとして表示します。

はJavaでは、使用してarray.containsは、任意の遅れを生じさせないために十分速かったが、それに追加されheightForRowAtを呼び出すときに、セルを移入する場合、より多くのコメントIDとして増加の遅れにつながるスウィフトバージョンはgetRealPosition機能を何度も呼び出します「隠れた」配列

配列の "contains"検索の速度を向上させる方法はありますか(おそらく別の種類のコレクションを使用します)。私はアプリケーションでプロファイリングを行い、「含む」は最も時間を要した方法でした。

は、私はあなたがソース配列にテーブルビュー内の行のタップからリンクするrealPositionが必要だと思うあなた

+1

は 'NSOrderedSet'を使用してみてください?私はそれが特にSwift-yのアプローチではないことを認識していますが、順序付きセットは最大スピードメンバーシップテストに必要なものです。あるいは、Swift 'OrderedSet'の[このオープンソース実装](https://github.com/Weebly/OrderedSet)を試すこともできます。 –

+0

問題は「含む」ではありません。問題は、私が信じているのは、表示したいデータとそれを使ってやりたいことが、データモデルが間違っていることです。瞬時にデータを手に入れることができない場合は、データモデルが間違っています。 – matt

答えて

1

ありがとうございましたか!

1)この新しい配列にすべての可視要素のみtableViewDataSource

コピーのためのデータと二番目の配列を作ります。特別なViewModelを、テーブルビューに表示するためのネッセサリデータのみを持つクラスまたはより良い構造体として作成します。この新しいViewModelに、realdatapositionも値として保存します。今、あなたがソース配列

2へのバックリンクを持っている)、その後

3唯一の新しいデータソースからこのテーブルビューを移入)が迅速にfunctional programmingに多くを見て - そこにあなたがよりよい例えば配列の上に行くことができます:

var array1 = ["a", "b", "c", "d", "e"] 
let array2 = ["a", "c", "d"] 
array1 = array1.filter { !array2.contains($0) } 

またはあなたのケースで :

let newArray = comments.filter{ !hidden.contains($0.getId()) } 

かのviewmodelを作成するために列挙

struct CommentViewModel { 
    var id: Int 
    var text: String 
    var realPosition: Int 
} 

let visibleComments: [CommentViewModel] = comments 
    .enumerated() 
    .map { (index, element) in 
     return CommentViewModel(id: element.getId(), text: element.getText(), realPosition: index) 
    } 
    .filter{ !hidden.contains($0.id) }  
+0

大変ありがとうございました!データセットからアイテムを取り出したときに新しい配列をフィルタリングしてしまい、その新しい配列を使ってgetHiddenCountUpToを使わずにデータを設定しました。これにより、全体の処理が大幅に高速化されました。間違いなく、オーバーヘッドの少ないより良いモデルを作成します – ccrama

4

JavaとSwiftの両方が、配列に含まれるすべての要素を通過する必要があります。配列が大きくなるにつれ、これは遅くなり、遅くなります。

Javaはまったく同じアルゴリズムを使用しているため、Javaがうまくいくのは先験的な理由はありません。しかし、文字列は各言語で非常に異なって実装されているため、Swiftでは文字列の比較が高価になる可能性があります。

いずれにしても、文字列比較が遅くなる場合は、回避する必要があります。

簡単修正:あなたは、単純なパフォーマンスの向上をしたい場合に設定

を使用するには、文字列の集合を文字列の配列を置き換えることができます。 Swiftのセットはハッシュテーブルで実装されています。つまり、一定時間のクエリが必要です。実際には、これは大きなセットの場合、より良いパフォーマンスが得られることを意味します。最高のパフォーマンスを得るため

var hiddenset Set<String> = {} 
    for item in hidden { 
     strset.insert(item) 
    } 

:BitSetの

を使用しますが、あなたもセットで行うことができるより全体の多くより良いを行うことができるはず。あなたは、常にこのようにしhiddenにアクセスしている場合、私たちはあなたのコードで

hidden.contains(comments[i].getId())) 

を見てみましょう、それは何を持っていることは、ブール値(trueまたはfalse)の整数(i)からマップであることを意味しています。

その後、次の...

import Bitset; 

    let hidden = Bitset(); 
    // replace hidden.append(comments[i].getId())) by this: 
    hidden.add(i) 
    // replace hidden.contains(comments[i].getId())) by this: 
    hidden.contains(i) 

次に、あなたのコードは本当に飛ぶを行う必要があります!

スウィフトで速いのBitSetの実装を使用するには、(それはフリーソフトウェアです)Package.swiftに、次のものがあります。

import PackageDescription 

    let package = Package(
     name: "fun", 
     dependencies: [ 
     .Package(url: "https://github.com/lemire/SwiftBitset.git", majorVersion: 0) 
     ] 
    )