如何在ruby中处理这个数组?

时间:2014-12-16 08:52:09

标签: ruby arrays

有一个这样的数组:

    arr = [
        {id: 1, status: 3},
        {id: 2, status: 5},
        {id: 3, status: 5},
        {id: 4, status: 5},
        {id: 5, status: 5},
    ]

在此数组中,如果任何散列的状态为3,则将更改为2,而其他散列将更改为1.如果每个散列状态不为3,则数组不会更改。

我希望输出应该是:

    arr = [
        {id: 1, status: 2},
        {id: 2, status: 1},
        {id: 3, status: 1},
        {id: 4, status: 1},
        {id: 5, status: 1},
    ]

如果数组如下:

    arr = [
        {id: 1, status: 2},
        {id: 2, status: 5},
        {id: 3, status: 5},
        {id: 4, status: 5},
        {id: 5, status: 5},
    ]

每个散列状态不是3,因此数组不会改变。

我可以这样做:

    tmp = false
    arr.each do |e|
        if e[:status].to_i == 3
           e[:status] = 2
           tmp = true
           break
        end
    end
    // note: if tmp == false, the array does not change
    if tmp == true
        arr.each do |e|
            e[:status] = 1  if e[:status].to_i == 5
        end
    end

但我认为这是一个坏主意,它会循环两次。谁有更好的解决方案?提前谢谢!

6 个答案:

答案 0 :(得分:1)

如果第一个数组元素是status: 3,则提交的大多数答案只能正常工作。

你可以在一个循环中完成它,如果你在去的时候构建一个数组的副本,如果找到一个匹配就交换原来的那个

arr = [
        {id: 1, status: 3},
        {id: 2, status: 5},
        {id: 3, status: 5},
        {id: 4, status: 5},
        {id: 5, status: 5},
];


switch = false
new_arr = Array(arr.length)

arr.each_with_index do |e,i|
  if e[:status] == 3
    new_elem = { id: e[:id], status: 3 }
    switch = true
  else
    new_elem = { id: e[:id], status: 1 }
  end
  new_arr[i] = new_elem
end

arr = new_arr if switch

因此,您不必迭代整个数组两次,但如果没有状态,则构造一个未使用的副本数组:3。

我认为您可能需要考虑使用不同的数据结构 - 可能是一个特定的类,用于模拟您正在使用的状态更改。也许看看一些状态机宝石。

答案 1 :(得分:0)

arr.map do |e|
  new_status = if e[:status] == 3
                 2
               else
                 1
               end
  {id: e[:id], status: new_status}
end

答案 2 :(得分:0)

我想你可以使用三元:

arr.each{|element| element[:status] == 3 ? element[:status] = 2 : element[:status] = 1}

答案 3 :(得分:0)

arr.map do |e|
   {id: e[:id], status: (e[:status]==3) ? 2 : 1}
end

答案 4 :(得分:0)

再次使用find_all,但是更清洁。

arr.find_all {|e| e[:status] = 2 if e[:status] == 3  }
arr.find_all {|e| e[:status] = 1 if e[:status] == 5  }

答案 5 :(得分:0)

没有办法避免两个循环,因为在知道是否需要更改<!DOCTYPE html> <html ng-app=""> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>H</title> <!-- STYLESHEETS --> <link rel="stylesheet" href="/assets/common/css/split.css"> <link rel="stylesheet" href="/assets/common/css/control.css"> <!-- JQUERY --> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script src="/assets/common/js/bootstrap.min.js" type="text/javascript"> </script> <script src="/assets/common/js/control.js" type="text/javascript"></script> <!-- ANGULAR --> <script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script> </head> <body id="home"> <div ng-include="'../assets/includes/left-panel.html'"></div> <!-- / START TEMPLATE --> <div ng-include="'../assets/includes/template.html'"></div> </body> </html> 的值之前,必须确定arr[i][:status] => 3是否为i arr[j][:status]所有2的{​​}}或1}。这是你可以这样做的一种方式:

j