如何通过不同位置的元组元素组合两个通道?

How combine two channels by tuple elements in different positions?

我必须像这样组合两个不同通道的输出:

first_output = Channel.from(['H100_BDNA', 'sed'], ['H100_nova', 'rip'], ['H100_hiseq', 'bam2'])
second_output= Channel.from(['pAdna', 'H100_hiseq', '11'], ['pAsc', 'H100_BDNA', '45'], ['iMes', 'H100_BDNA', '58'], ['pAsc1', 'H100_nova', '23'])

想要的结果应该是:

['pAdna', 'H100_hiseq', '11', 'bam2'], 
['pAsc', 'H100_BDNA', '45', 'sed'], 
['iMes', 'H100_BDNA', '58', 'sed'], 
['pAsc1', 'H100_nova', '23', 'rip']

这意味着通过由第一个输出中元组的第一个元素和第二个通道中的第二个元素表示的公共键连接通道。 我尝试了很多操作员,但没有一个工作。 我该怎么做?

据我所知,在 nextflow 中,如果两个通道的位置不同,则无法指定 join-key 位置(by 适用于两个通道)。我通常处理它的方式是,我首先以某种方式重新排列两个通道中的元组,可以使用 mapswap.

连接它们

对于您的示例(加入 first_output,key = 0 和 second_output key = 1,然后重新排序以获得所需的输出顺序)方法如下所示:

second_output
    .map{it.swap(1,0)} // swap item 0 and 1
    .join(first_output) // now join on item 0
    .map{it.swap(1,0)} // swap back
    .set { joined_output }

编辑: 我刚刚意识到,第一个输出中有 3 个元组,第二个输出中有 4 个元组。 nextflow 关于 join 的行为确实不直观,如 this discussion

中所述

他们还提供了一个变通函数“inner_join”:

def inner_join(ch_a, ch_b) {
    return ch_b.cross(ch_a).map { [it[0][0], *it[1][1..-1], *it[0][1..-1]] }
}

使用这个函数你的解决方案是(仍然交换位置):

inner_join(second_output.map{ it.swap(1,0) }, first_output)
    .map{ it.swap(1,0) }
    .set { joined_output }

我想你想要的是decorate-combine-undecorate:

second_output
    .map { tuple( it[1], *it ) }
    .combine( first_output, by: 0 )
    .map { it[1..-1] }
    .view()

结果:

[pAdna, H100_hiseq, 11, bam2]
[pAsc, H100_BDNA, 45, sed]
[iMes, H100_BDNA, 58, sed]
[pAsc1, H100_nova, 23, rip]

这是通过在第二个通道中的元素前面加上要使用的键来实现的 combine the items in the first channel. Note that we use the 'second version' of the combine operator to combine only those items that share a common key. Finally, we 'remove' the shared key by selecting all elements except the first element. See also: Schwartzian transform