2013-05-09 55 views
0

我有三个数组。如何基于第三个数组的顺序合并Ruby中两个数组的项目?

我的主列表包含在数据库验证不同实体的组合:

ab = ["a:555", "b:222", "a:333", "b:777", "a:777", "a:999", "b:111"] 

我有a两个阵列和分离b的实体,而是有序的(有些是丢失):

# notice that some of the items from the initial list are missing, but the order is preserved! 
a = [{id}, "a:777", "a:999"] 
b = ["b:222", "b:111"] 

什么是合并ab的有效方法c保留ab中存在项目的顺序?我的程序的预期结果是:

c = ["a:555", "b:222", "a:777", "a:999", "b:111"] 

我是一个红宝石新手,我想出的一切都是完全丑陋的。


编辑:

我知道它很重要,并会混淆,但ab是复杂的对象(AR)表示在ab的字符串。为了我的代码澄清:

ab = ["a:555", "b:222", "a:333", "b:777", "a:777", "a:999", "b:111"] 
a = [{:id => 555}, {:id => 777}, {:id => 999}] 
b = [{:id => 222}, {:id => 111}] 
c = [] 

ab.each { |item| 
parts = item.split(":") 
if parts[0] == "a" 
    if a[0][:id].to_s() == parts[1] 
    c << a.shift() 
    end 
else 
    if b[0][:id].to_s() == parts[1] 
    c << b.shift() 
    end 
end 

} 

puts c 
+2

对不起,我没有抓住它。你想到了什么? – oldergod 2013-05-09 09:03:29

+0

是的,问题很混乱。 – 2013-05-09 09:06:09

+0

将在一分钟内添加我的代码。 – ddinchev 2013-05-09 09:07:44

回答

3

如果该值的id不是A和B之间的不同,我们可以做到这一点

c = (
    a.map { |e| [ "a:#{e[:id]}", e ] } + 
    b.map { |e| [ "b:#{e[:id]}", e ] } 
). 
sort_by { |e| ab.index(e.first) }. 
map(&:last) 

既然你现在说明他们是不同的,并且有一个方法上产生你的AB键的对象,这是简单的:

c = (a + b).sort_by { |e| ab.index(e.get_ab_string) } 

ab.index是O在AB(N)操作,所以它升级什么是通常一个NlnN排序,以N^2。为了使整个溶液放回O(NlnN)运行时,可以预先calaculate AB的索引为哈希(一个O(N)的操作允许O(1)在sort_by查找):

ab_idx = Hash[ ab.map.with_index { |e,i| [e, i] } ] 
c = (a + b).sort_by { |e| ab_idx(e.get_ab_string) } 
+0

为什么需要'Sort_by'? – 2013-05-09 10:53:32

+0

最后一行,真棒。如果可以的话,我会提供两次。 – ddinchev 2013-05-09 12:07:40

+0

@Priti你的问题让我困惑。 'sort_by'比你选择'any?'答案更简单,更高效。运行sort_by的复杂度为O(N lnN);你选择了什么?是O(N^2) – dbenhur 2013-05-09 14:53:26

0

以下是如何将数组按相同顺序排序的基础。

ary_a = %w[one four three two] 
ary_b = [1, 4, 3, 2] 

将它们合并,排序,然后检索一个我们想要的分类:有两个数组开始

ary_a.zip(ary_b).sort_by{ |a, b| b }.map(&:first) 
=> ["one", "two", "three", "four"] 

如果我们想颠倒顺序:

ary_a.zip(ary_b).sort_by{ |a, b| -b }.map(&:first) 
=> ["four", "three", "two", "one"] 

或:

​​

如果有三个阵列ys和两个需要与第三个一起定购:

ary_c = %w[a-one a-four a-three a-two] 
ary_a.zip(ary_c).zip(ary_b).sort_by{ |a, b| b }.map(&:first) 
=> [["one", "a-one"], ["two", "a-two"], ["three", "a-three"], ["four", "a-four"]] 

在合并和排序之前将数组转换为所需的形式是问题所在。一旦你有了这些,并且它们有相同数量的元素,这是一个非常简单的模式。