2017-01-18 8 views
0

配列の各要素は、構造体のインスタンスです。配列[モデルA、モデルB、モデルC、モデルD、モデルE]です。構造体には「名前」というプロパティがあります。たとえば...配列の同じプロパティ値を持つ要素をグループ化する

modelA.name = "abc" 
modelB.name = "efg" 
modelC.name = "hij"  
modelD.name = "abc" 
modelE.name = "efg" 

同じプロパティ値を持つ要素を新しい配列にグループ化するにはどうすればよいですか?すなわちをmodelAに、modelDを新しい配列に入れ、modelBとmodelEを別の配列に配置します。

元の配列がと大きいとします。です。

+1

'var d [String:[Model]];で何が問題になるでしょうか。私は配列の中で{let m = array.filter {$ 0.name == i.name}; if m.count> 1 {d [i.name] = m}} '? – Grimxn

+0

http://stackoverflow.com/questions/31220002/how-to-group-by-the-elements-of-an-array-in-swiftこれは私の質問を解決します、皆のためにありがとう – Tom

答えて

2

あなたはfilter(_:)を使用することによって、これを達成することができます:

は、順番に、与えられた述語を満たすシーケンス の要素を含む配列を返します。例えば

、構造がどのように見えることを考慮してください。

struct Model { 
    var name: String? 
} 

そして、あなたは、モデルの配列を持っている:

let allModelsArray = [Model(name: "abc"), Model(name: "efg"), Model(name: "hij"), Model(name: "abc"), Model(name: "efg"), Model(name: "efg"), Model(name: "hij")] 

だから、あなたがいることを想定して(実行して、配列を得ることができますnameの値に基づいてフィルタリングする必要があります)。

let abcModelsArray = allModelsArray.filter { $0.name == "abc" } 
// [Model(name: Optional("abc")), Model(name: Optional("abc"))] 

let hijModelsArray = allModelsArray.filter { $0.name == "hij" } 
// [Model(name: Optional("hij")), Model(name: Optional("hij"))] 
ALSO

あなたがいることを述べた:

は、どのように私は、このような新しい配列にMODELAとmodelDを入れて、入れて、新しい 配列に同じプロパティ値を持つ要素を入れることができますmodelB とモデルEを新しい配列に追加すると、の場合はとなります。

どうにかして、コレクションのバージョンlazyを使用したい場合があります。

これが役に立った。

let a = [modelA, modelB, modelC, modelD, modelE] 

let arr = a.reduce([:]) { (result, currentModel) -> [String: [Model]] in 
    var mutableDic = result 
    if ((mutableDic[currentModel.name]) != nil) { 
     mutableDic[currentModel.name]?.append(currentModel) 
    } else { 
     mutableDic[currentModel.name] = [currentModel] 
    } 

    return mutableDic 
} 

それは@Grimxn応答と同じ辞書を返します。

+0

これについては知っているでしょうすべての名前で始まる。これはせいぜいO(n^2)になります。私は@Grimxnのコメントはこれのためのより良い解決策であり、それはO(n)であると思います。 – Fogmeister

+0

@Fogmeister - コメントをいただきありがとうございますが、自分自身がO(n)で、forループが掛けられているので、私はまだO(n^2)です... – Grimxn

+0

@Grimxn私はあなたのコメントを意味しました。あなたの答えは見えませんでした。 :-) ああ。また、私はあなたのコメントを誤解しました:-) – Fogmeister

1

は私がいないのパフォーマンスは、この

struct Model { 
    var type : String 
    var name : String 
} 
var modelA = Model(type: "A", name: "abc") 
var modelB = Model(type: "B", name: "efg") 
var modelC = Model(type: "C", name: "abc") 
var modelD = Model(type: "D", name: "efg") 

let models = [modelA,modelB,modelC,modelD] 

let names = Set(models.map({return $0.name})) 

var groupedModels : [String:[Model]] = [:] 
for var name in names { 
    let elements = models.filter({$0.name == name}) 
    groupedModels[name] = elements 
} 
+0

あなたの答えの良い部分は、 'name'が不明であると仮定していることです。 –

1

.reduceソリューションをテストしています。あるいは、このfor loop

var mutableDic = [String : [Model]]() 

     for aModel in a { 
      if ((mutableDic[aModel.name]) != nil) { 
       mutableDic[aModel.name]?.append(aModel) 
      } else { 
       mutableDic[aModel.name] = [aModel] 
      } 
     } 

から鍵が、それは.nameだと比較することにより、同じ配列に格納する必要があるモデルのために追跡するために、辞書を使用することですしまいました。

+0

これは私よりも優れた候補者のようです。最初はO(n)です。 – Grimxn

+0

ニットのピッキングですが、私の場合と同じ名前が返されるわけではありません。 – Grimxn

関連する問題