2016-11-17 65 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