2016-11-17 63 views
0

我有一些非常簡單的.NET邏輯,我正將其移植到Scala代碼庫中,而我並不真正瞭解Scala的第一件事。它包括一個LINQ查詢組標記對象的集合通過使用匿名類型投影的扁平化和加入,其次爲分組,例如:在Scala中的LINQ SelectMany相當於

var q = things.SelectMany(t => t.Tags, (t, tag) => new { Thing = t, Tag = tag }) 
       .GroupBy(x => x.Tag, x => x.Thing); 

在Scala中,它看起來像flatMap可能是有用的,但我無法弄清楚如何通過匿名將它與groupBy結合起來。

這種事情在Scala中更加複雜嗎?還是我錯過了一些簡單的東西?

UPDATE:

我結束了去:

things.flatMap(t => t.Tags.map(x => (x,t))).groupBy(x => x._1) 

然後當然後來當我在地圖中存取的值,我需要做的事:

.map(x => x._2) 

到從組中取出組。

簡單,當你知道如何!

+0

我沒有完全按照你想要完成的工作,你能改正你的C#示例。 SelectMany只接受一個輸入(除了'this'參數的擴展名),你似乎有兩個輸入。此外,你的括號不平衡,並且弄清楚你想讓他們去的地方。 – Danny

+0

我看到你添加了缺少的括號,但你的'SelectMany'有太多的參數源和選擇器方法https://msdn.microsoft.com/en-us/library/bb534336(v=vs.110).aspx但你似乎在提供兩種方法 – Danny

+0

對不起,錯過了一個家長。 – lesscode

回答

1

對我來說,你想要做類似的事情。

case class Tag(tag:String) 

case class Thing(Tags : Seq[Tag]) 

val things :Seq[Thing] = Seq(Thing(Seq(Tag("")))) 

val q = things.map { 
    thing => new { 
    val Thing = thing 
    val Tags = thing.Tags 
    } 
}.flatMap { 
    thingAndTags => thingAndTags.Tags.map { 
    tag => new { 
     val Thing = thingAndTags.Thing 
     val Tag = tag 
    } 
    } 
}. groupBy { 
    thingAndTag => thingAndTag.Tag 
}.map { 
    tagAndSeqOfThingAndTags => 
    tagAndSeqOfThingAndTags._1 -> tagAndSeqOfThingAndTags._2.map(x => x.Thing) 
} 

但Scala的匿名對象是不是真的常見,但你可以使用Tuple2[T1,T2],而不是所有的new { val ...} S的,

val q = things.map { 
    thing => (thing->thing.Tags) 
}.flatMap { 
    thingAndTags => thingAndTags._2.map { 
    tag => (thingAndTags._1, tag) 
    } 
}.groupBy { 
    thingAndTag => thingAndTag._2 
}.map { 
    tagAndSeqOfThingAndTags => 
    tagAndSeqOfThingAndTags._1 -> tagAndSeqOfThingAndTags._2.map(x => x._1) 
} 

它只是有點混亂,所有的._1 S和._2小號

+0

謝謝。我最終結束了與元組。 Scala中缺少的部分是提供結果/元素選擇器的能力,我認爲,但它仍然非常簡潔。 – lesscode

+0

@lesscode如果你真的想要通過使用從Seq到「RichSeq」(或任何你想命名的)的隱式轉換,爲'flatmap'和'groupby'方法創建「覆蓋」,所以你的代碼看起來更像C#當量 – Danny