2017-11-16 9 views
0

私のモデルで私はCarエンティティを持っています。コアデータクエリ、最新の年あたりの自動車?

カー 年 CREATEDATE 名

私は(名前がnilすることができます)名前がnilでない、年間のすべての最も最近の車を返すフェッチを実行したいです。

したがって、私は2000年と3台の車と2010年の車がある場合、フェッチ要求から合計2台の車を取得したいと思います(2000年の最新のものと2010年のもの) 。

これを達成するための適切な述語を書く方法がわかりません。私はreturnsDistinctResultsオプションを調べましたが、正しいパスであることがわかりませんし、NSDictionaryResultTypeでしか動作しません。

これを行うための適切なクエリ/述語は何でしょうか?

答えて

1

アルゴリズムを使用して各レコードを実行する方がよいでしょう。

Carクラスを許可するには、次のように定義します。

struct C { 
    var year: Int 
    var created: Date 
    var name: String? 
} 

var cars = [C(year: 2009, created: Date(), name: nil), C(year: 2009, created: Date(), name: "Green"), C(year: 2010, created: Date(), name: "Green"), C(year: 2010, created: Date(), name: "Orange"), C(year: 2010, created: Date(), name: "Orange")] 

var carsPerYear = [Int: [String: Int]]() 

for car in cars { 
    if let name = car.name { 
     var info: [String: Int]? = nil 
     if carsPerYear.keys.contains(car.year) { 
      info = carsPerYear[car.year] 
     } else { 
      info = [String: Int]() 
     } 
     if !info!.keys.contains(name) { 
      info![name] = 0 
     } 
     info![name] = info![name]! + 1 
     carsPerYear[car.year] = info 
    } 
} 

for year in carsPerYear.keys { 
    let info = carsPerYear[year]! 
    let sorted = info.keys.sorted{ info[$0]! > info[$1]! } 
    print(year, sorted.first!) 
} 

が時々SQLまたはCoreDataは簡単な問題を解決することはできません出力

2009 Green 
2010 Orange 

を与え、それだけでソートアルゴリズムを記述するのが最善です。

-1

アルゴリズムに年の配列を渡し、辞書の形式で結果を期待している場合は、これを達成できます。毎年、そのオブジェクトに対応するオブジェクトのキーとして渡されます。その年の最も最近の車。

すなわち:

let years : [Int] = [2000, 2005] 


//The ideal method: 

func mostRecentFor<T>(years: [Int]) -> [String:T] 

だけ検索年間の小さな番号を使用すると仮定し、データベースが車の数が少ないこと、あなたがスレッドを心配する必要はありません。それ以外の場合は、この方法では並行性を使用するか、フェッチのための専用スレッドを使用してメインスレッドをブロックしないようにする必要があります。テスト目的のために、必要はありません。

これを達成するには、次の行に沿った方法を使用します。

まず、他の回答が示唆しているように、その年に番号述語を使用する必要があります。あなたがNSPredicateの日付形式を使用します。このために :

NSPredicate(format: "date == %@", year) 

あなたのモデルは、それゆえ、パラメータ別として、実際のnsdateとして年間持っている必要があります。次に、fecthLimitパラメータを1に設定し、sortDescriptorをnsDateキーパラメータに適用します。後の2つを組み合わせることで、指定された年の最年少または最古の値のみが返されます。我々は最初の値、実際に原因1のfetchLimit値に戻ったものをしたいので、私たちが言った、今年の早い車、または最小と一つであることが、ここではtrueにセットを昇順使用

func mostRecentFor(years: [Int]) -> [String:Car] { 
     let result : [String:Car] = [:] 
     for year in years { 
      let request: NSFetchRequest<CarModel> = CarModel.fetchRequest() 
      request.predicate = NSPredicate(format: "date == %@ AND name != nil", year) 
      request.fetchLimit = 1 
      let NSDateDescriptor: let sectionSortDescriptor = NSSortDescriptor(key: "nsDate", ascending: true) 
      let descriptors = [NSDateDescriptor] 
      fetchRequest.sortDescriptors = descriptors 
      do { 
       let fetched = try self.managedObjectContext.fetch(request) as 
       [CarModel] 
       guard !fetched.isEmpty, fetched.count == 1 else { 
        print("No Car For year: \(year)") 
        return 
       } 
       result["\(year)"] = new[0].resultingCarStruct //custom parameter here.. see bellow 
      } catch let err { 
       print("Error for Year: \(year), \(err.localizedDescription)") 
      } 
     } 
     return result 
} 

nsDateキーのタイムスタンプ。

これは、小さなデータストアとテストのための簡単なフェッチクエリを提供します。また、CarModelをCar structの対応部分に解釈するためのメソッドやパラメータを作成すると、CDからメモリオブジェクトに簡単に移動できます。

だからあなたはそうのようなあなたの車を探したい:

let years = [1985, 1999, 2005] 
let cars = mostRecentFor(years: years) 

// cars = ["1985": Car<year: 1985, name: "Chevrolet", nsDate: "April 5th 1985">, "1999" : Car<year: 1999, name: "Toyota Corolla", nsDate: "February 5th 1999">] 
// This examples suggests that no cars were found for 2005 
+0

私はこれで三つの問題、あなたは何を意味するかを参照してください。1.このアプローチは、ディスクに非常に非常に遅いトンを、行きます。 2.この質問は年を重ねることを求めているわけではなく、毎年最新の車がほしいと思っています3.この答えは名前=!nilの状態を考慮に入れません。ありがとう。 – zumzum

+0

1:私は、このアプローチが小さなdbをテストするのに適していると指定しており、それを何かのためのconcurencyラッパーに適合させる必要があると指定します。 2:「毎年」とは、1年間のコレクションから、2年の間の毎年までの何かを意味することができます。これは、少なくとも年の配列(またはこの場合は整数)になります。 3:確かに名前を忘れてしまい、nilをチェックするには、述語文字列にAND演算子を追加し、文字列内またはパラメタ表記のどちらかで回避値を追加します。病気のアップデート – murphguy

+0

これは、質問が求めている答えを提供していません。ごめんなさい。 – zumzum

関連する問題