2014-03-05 30 views
2

所以,这里有一个问题。我想要做的是给定一组输入值来生成一个数据结构。生成聚合结构

由于这是一个多语言提交,我们来看看输入列表是一个键/值对数组。因此,一组哈希,地图,字典或任何术语漂浮你的船。我将把这里的所有符号保留为JSON,希望这足够通用来翻译/解码。

所以对于输入,让我们说我们有这个:

[ { "4": 10 }, { "7": 9 }, { "90": 7 }, { "1": 8 } ] 

也许有点多余,但让我们坚持这一点。

所以从那个输入我想要到这个结构。我给一个整体结构,但重要的部分是什么获取下“权重”返回值:

[ 
    { "$project": { 
     "user_id": 1, 
     "content": 1, 
     "date": 1, 
     "weight": { "$cond": [ 
      { "$eq": ["$user_id": 4] }, 
      10, 
      { "$cond": [ 
       { "$eq": ["$user_id": 7] }, 
       9, 
       { "$cond": [ 
        { "$eq": ["$user_id": 90] }, 
        7, 
        { "$cond": [ 
         { "$eq": ["$user_id": 1] }, 
         8, 
         0 
        ]} 
       ]} 
      ]} 
     ]} 
    }} 
] 

所以我在寻找解决方案填充结构内容“重“如结构所示,通过使用输入所示。

是的,这看起来像在结构号码必须是数字,而不是字符串的值,所以无论语言实现的JSON编码版本必须长得一模一样。

或者,给我一个更好的方法去分配基础上,匹配user_id重量值相同的结果。

有没有人有办法呢?

对于任何语言实现都会感到满意,因为我认为只要看看如何创建结构就很公平。

我会尝试添加自己,但荣誉去良好的实现。

快乐编码。

+0

哦如果你做出了反对票或者近距离投票,为什么要给出合理的解释。事实上,像这样的结构需要**生成**,所以如果你不明白,那么请提出问题或者继续前进。我的政策是自我解释,所以内容可以改变或者根本不做任何事情。即使你没有,其他人也可能会明白。 –

回答

2

当我有时间去思考这件事,我跑回家Perl和工作了这一点:

use Modern::Perl; 

use Moose::Autobox; 
use JSON; 

my $encoder = JSON->new->pretty; 

my $input = [ { 4 => 10 }, { 7 => 9 }, { 90 => 7 }, { 1 => 8 } ]; 

my $stack = []; 

foreach my $item (reverse @{$input}) { 

    while (my ($key, $value) = each %{$item}) { 
    my $rec = { 
     '$cond' => [ 
     { '$eq' => [ '$user_id', int($key) ] }, 
     $value 
     ] 
    }; 

    if ($stack->length == 0) { 
     $rec->{'$cond'}->push(0); 
    } else { 
     my $last = $stack->pop; 
     $rec->{'$cond'}->push($last); 
    } 

    $stack->push($rec); 
    } 

} 

say $encoder->encode($stack->[0]); 

所以这个过程是令人眼花缭乱的简单。

  1. 通过阵列中的每个项目去,并获得进入

  2. 键和值创建一个新的“文件”已在数组变量的“$ COND”键只有两个要求的三项。这些是分配给测试“$ user_id”和返回的“权重”值的值。

  3. 测试外部变量的长度为,并且如果它是空的(第一时间通过),那么如看到在过去嵌套元素到“$ COND的端部的0值“文件中的关键。

  4. 如果有东西已经存在(长度> 0),那么取这个值并且作为文档的“$ cond”键中的第三个值。

  5. 把这份文件早在的价值再次为下一个项目

因此,有在上市的几件事情,如颠倒输入的订单,这”不是个t是必需的,但在嵌套输出中产生自然顺序。此外,我对外部“堆栈”的选择是一个数组,因为测试操作员看起来很简单。但它确实只是一个不断重复使用,扩充和替换的奇异值。

另外JSON打印就在那里显示输出。所有真正需要的是将堆栈的合成值合并到结构中。

然后我转换的逻辑到红宝石,因为是通过从在那里我得到为如何产生这种嵌套结构的灵感OP中使用的语言:

require 'json' 

input = [ { 4 => 10 }, { 7 => 9 }, { 90 => 7 }, { 1 => 8 } ] 

stack = [] 

input.reverse_each {|item| 

    item.each {|key,value| 
    rec = { 
     '$cond' => [ 
     { '$eq' => [ '$user_id', key ] }, 
     value 
     ] 
    } 

    if (stack.length == 0) 
     rec['$cond'].push(0) 
    else 
     last = stack.pop 
     rec['$cond'].push(last) 
    end 

    stack.push(rec) 
    } 

} 

puts JSON.pretty_generate(stack[0]) 

,然后最终成最终的形式,以产生该OP想要管道:

require 'json' 

userWeights = [ { 4 => 10 }, { 7 => 9 }, { 90 => 7}, { 1 => 8 } ] 

stack = [] 

userWeights.reverse_each {|item| 

    item.each {|key,value| 
    rec = { 
     '$cond' => [ 
     { '$eq' => [ '$user_id', key ] }, 
     value 
     ] 
    } 

    if (stack.length == 0) 
     rec['$cond'].push(0) 
    else 
     last = stack.pop 
     rec['$cond'].push(last) 
    end 

    stack.push(rec) 
    } 

} 

pipeline = [ 
    { '$project' => { 
     'user_id' => 1, 
     'content' => 1, 
     'date' => 1, 
     'weight' => stack[0] 
    }}, 
    { '$sort' => { 'weight' => -1, 'date' => -1 } } 
] 

puts JSON.pretty_generate(pipeline) 

所以这是产生结构的方式,以应用“权重”所特有的一个user_id和集合中的结果进行排序要传递到骨料。

2

首先非常感谢Neil对您的帮助here,这个锻炼非常适合我,而且速度非常快。对于那些谁使用mongoid,这是我用来创建权重参数,其中recommended_user_ids是一个数组:

def self.project_recommended_weight recommended_user_ids 
     return {} unless recommended_user_ids.present? 
     {:weight => create_weight_statement(recommended_user_ids.reverse)} 
    end 

    def self.create_weight_statement recommended_user_ids, index=0 
     return 0 if index == recommended_user_ids.count 
     {"$cond" => [{ "$eq" => ["$user_id", recommended_user_ids[index]] },index+1,create_weight_statement(recommended_user_ids,index+1)]} 
    end 

所以,把它添加到管道简单地合并这样的哈希:

{"$project" => {:id => 1,:posted_at => 1}.merge(project_recommended_weight(options[:recommended_user_ids]))}