ruby - 我该如何改进?

标签 ruby

我想知道是否有人可以指出一种更简洁、更好的方法来编写粘贴在此处的代码。该代码从 yelp 中抓取一些数据并将其处理为 json 格式。我不使用 hash.to_json 的原因是因为它会抛出某种堆栈错误,我只能假设是由于散列太大(它不是特别大)。

  • 响应对象 = 哈希
  • text = 保存到文件的输出

无论如何指导表示赞赏。

def mineLocation

  client = Yelp::Client.new
  request = Yelp::Review::Request::GeoPoint.new(:latitude=>13.3125,:longitude => -6.2468,:yws_id => 'nicetry')
  response = client.search(request) 
  response['businesses'].length.times do |businessEntry|
    text =""
     response['businesses'][businessEntry].each { |key, value|
        if value.class == Array 
          value.length.times { |arrayEntry|
            text+= "\"#{key}\":["
             value[arrayEntry].each { |arrayKey,arrayValue|
              text+= "{\"#{arrayKey}\":\"#{arrayValue}\"},"
             }
             text+="]"   
          }
        else 
              text+="\"#{arrayKey}\":\"#{arrayValue}\"," 
        end
       }
  end
 end

最佳答案

看起来你所有的代码最终都是这样的:

require 'json'

def mine_location
  client = Yelp::Client.new
  request = Yelp::Review::Request::GeoPoint.new(latitude: 13.3125,
    longitude: -6.2468, yws_id: 'nicetry')
  response = client.search(request)

  return response['businesses'].to_json
end

这对我来说很好。

如果出于某种原因您确实必须编写自己的 JSON 发射器实现,这里有一些提示。

您在代码中完全忽略的第一件事是 Ruby 是一种面向对象的语言,更具体地说,是一种基于类的面向对象语言。这意味着通过构建一个对象网络来解决问题,这些对象通过消息传递相互通信,并通过执行这些对象所属的类中定义的方法来响应这些消息。

这给了我们很大的力量:动态分派(dispatch)、多态、封装和大量其他。利用这些,您的 JSON 发射器将如下所示:

class Object
  def to_json; to_s                                                         end
end

class NilClass
  def to_json; 'null'                                                       end
end

class String
  def to_json; %Q'"#{to_s}"'                                                end
end

class Array
  def to_json; "[#{map(&:to_json).join(', ')}]"                             end
end

class Hash
  def to_json; "{#{map {|k, v| "#{k.to_json}: #{v.to_json}" }.join(', ')}}" end
end

mine_location 看起来和上面一样,除了明显没有 require 'json' 部分。

如果你想要你的 JSON 格式很好,你可以尝试这样的事情:

class Object
  def to_json(*) to_s    end
end

class String
  def to_json(*) inspect end
end

class Array
  def to_json(indent=0)
    "[\n#{'  ' * indent+=1}#{
      map {|el| el.to_json(indent) }.join(", \n#{'  ' * indent}")
    }\n#{'  ' * indent-=1}]"
  end
end

class Hash
  def to_json(indent=0)
    "{\n#{'  ' * indent+=1}#{
      map {|k, v|
        "#{k.to_json(indent)}: #{v.to_json(indent)}"
      }.join(", \n#{'  ' * indent}")
    }\n#{'  ' * indent-=1}}"
  end
end

实际上这段代码中没有任何特定于 Ruby 的内容。例如,这与任何其他基于类的面向对象语言(例如 Java)中的解决方案看起来完全差不多。这只是面向对象设计 101。

唯一特定于语言的是如何“修改”类并向它们添加方法。在 Ruby 或 Python 中,您实际上只是修改类。在 C# 和 Visual Basic.NET 中,您可能会使用扩展方法,在 Scala 中您会使用隐式转换,在 Java 中可能会使用装饰器设计模式。

您的代码的另一个巨大问题是您试图解决一个显然递归但实际上从未递归的问题。这只是不能工作。您编写的代码基本上是 Fortran-57 代码:没有对象和递归的过程。即使只是从 Fortran 移动一个步骤到,比如说,Pascal,也会给你一个很好的递归过程解决方案:

def jsonify(o)
  case o
  when Hash
    "{#{o.map {|k, v| "#{jsonify(k)}: #{jsonify(v)}" }.join(', ')}}"
  when Array
    "[#{o.map(&method(:jsonify)).join(', ')}]"
  when String
    o.inspect
  when nil
    'null'
  else
    o.to_s
  end
end

当然,你可以在这里用缩进玩同样的游戏:

def jsonify(o, indent=0)
  case o
  when Hash
    "{\n#{'  ' * indent+=1}#{
      o.map {|k, v|
        "#{jsonify(k, indent)}: #{jsonify(v, indent)}"
      }.join(", \n#{'  ' * indent}") }\n#{'  ' * indent-=1}}"
  when Array
    "[\n#{'  ' * indent+=1}#{
      o.map {|el| jsonify(el, indent) }.join(", \n#{'  ' * indent}") }\n#{'  ' * indent-=1}]"
  when String
    o.inspect
  when nil
    'null'
  else
    o.to_s
  end
end

这是 puts mine_location 的缩进输出,使用 to_json 的第二个(缩进)版本或 jsonify 的第二个版本生成,没关系,它们都有相同的输出:

[
  {
    "name": "Nickies",
    "mobile_url": "http://mobile.yelp.com/biz/yyqwqfgn1ZmbQYNbl7s5sQ",
    "city": "San Francisco",
    "address1": "466 Haight St",
    "zip": "94117",
    "latitude": 37.772201,
    "avg_rating": 4.0,
    "address2": "",
    "country_code": "US",
    "country": "USA",
    "address3": "",
    "photo_url_small": "http://static.px.yelp.com/bpthumb/mPNTiQm5HVqLLcUi8XrDiA/ss",
    "url": "http://yelp.com/biz/nickies-san-francisco",
    "photo_url": "http://static.px.yelp.com/bpthumb/mPNTiQm5HVqLLcUi8XrDiA/ms",
    "rating_img_url_small": "http://static.px.yelp.com/static/20070816/i/ico/stars/stars_small_4.png",
    "is_closed": false,
    "id": "yyqwqfgn1ZmbQYNbl7s5sQ",
    "nearby_url": "http://yelp.com/search?find_loc=466+Haight+St%2C+San+Francisco%2C+CA",
    "state_code": "CA",
    "reviews": [
      {
        "rating": 3,
        "user_photo_url_small": "http://static.px.yelp.com/upthumb/ZQDXkIwQmgfAcazw8OgK2g/ss",
        "url": "http://yelp.com/biz/yyqwqfgn1ZmbQYNbl7s5sQ#hrid:t-sisM24K9GvvYhr-9w1EQ",
        "user_url": "http://yelp.com/user_details?userid=XMeRHjiLhA9cv3BsSOazCA",
        "user_photo_url": "http://static.px.yelp.com/upthumb/ZQDXkIwQmgfAcazw8OgK2g/ms",
        "rating_img_url_small": "http://static.px.yelp.com/static/20070816/i/ico/stars/stars_small_3.png",
        "id": "t-sisM24K9GvvYhr-9w1EQ",
        "text_excerpt": "So I know gentrification is supposed to be a bad word and all (especially here in SF), but the Lower Haight might benefit a bit from it. At least, I like...",
        "user_name": "Trey F.",
        "mobile_uri": "http://mobile.yelp.com/biz/yyqwqfgn1ZmbQYNbl7s5sQ?srid=t-sisM24K9GvvYhr-9w1EQ",
        "rating_img_url": "http://static.px.yelp.com/static/20070816/i/ico/stars/stars_3.png"
      },
      {
        "rating": 4,
        "user_photo_url_small": "http://static.px.yelp.com/upthumb/Ghwoq23_alkaXawgqj7dBA/ss",
        "url": "http://yelp.com/biz/yyqwqfgn1ZmbQYNbl7s5sQ#hrid:8xTNOC9L5ZXwGCMNYY-pdQ",
        "user_url": "http://yelp.com/user_details?userid=4F2QG3adYIUNXplqqp9ylA",
        "user_photo_url": "http://static.px.yelp.com/upthumb/Ghwoq23_alkaXawgqj7dBA/ms",
        "rating_img_url_small": "http://static.px.yelp.com/static/20070816/i/ico/stars/stars_small_4.png",
        "id": "8xTNOC9L5ZXwGCMNYY-pdQ",
        "text_excerpt": "This place was definitely a great place to chill. The atmosphere is very non-threatening and very neighborly. I thought it was cool that they had a girl dj...",
        "user_name": "Jessy M.",
        "mobile_uri": "http://mobile.yelp.com/biz/yyqwqfgn1ZmbQYNbl7s5sQ?srid=8xTNOC9L5ZXwGCMNYY-pdQ",
        "rating_img_url": "http://static.px.yelp.com/static/20070816/i/ico/stars/stars_4.png"
      },
      {
        "rating": 5,
        "user_photo_url_small": "http://static.px.yelp.com/upthumb/q0POOE3vv2LzNg1qN8MMyw/ss",
        "url": "http://yelp.com/biz/yyqwqfgn1ZmbQYNbl7s5sQ#hrid:pp33WfN_FoKlQKJ-38j_Ag",
        "user_url": "http://yelp.com/user_details?userid=FmcKafW272uSWXbUF2rslA",
        "user_photo_url": "http://static.px.yelp.com/upthumb/q0POOE3vv2LzNg1qN8MMyw/ms",
        "rating_img_url_small": "http://static.px.yelp.com/static/20070816/i/ico/stars/stars_small_5.png",
        "id": "pp33WfN_FoKlQKJ-38j_Ag",
        "text_excerpt": "Love this place!  I've been here twice now and each time has been a great experience.  The bartender is so nice.  When we had questions about the drinks he...",
        "user_name": "Scott M.",
        "mobile_uri": "http://mobile.yelp.com/biz/yyqwqfgn1ZmbQYNbl7s5sQ?srid=pp33WfN_FoKlQKJ-38j_Ag",
        "rating_img_url": "http://static.px.yelp.com/static/20070816/i/ico/stars/stars_5.png"
      }
    ],
    "phone": "4152550300",
    "neighborhoods": [
      {
        "name": "Hayes Valley",
        "url": "http://yelp.com/search?find_loc=Hayes+Valley%2C+San+Francisco%2C+CA"
      }
    ],
    "rating_img_url": "http://static.px.yelp.com/static/20070816/i/ico/stars/stars_4.png",
    "longitude": -122.429926,
    "categories": [
      {
        "name": "Dance Clubs",
        "category_filter": "danceclubs",
        "search_url": "http://yelp.com/search?find_loc=466+Haight+St%2C+San+Francisco%2C+CA&cflt=danceclubs"
      },
      {
        "name": "Lounges",
        "category_filter": "lounges",
        "search_url": "http://yelp.com/search?find_loc=466+Haight+St%2C+San+Francisco%2C+CA&cflt=lounges"
      },
      {
        "name": "American (Traditional)",
        "category_filter": "tradamerican",
        "search_url": "http://yelp.com/search?find_loc=466+Haight+St%2C+San+Francisco%2C+CA&cflt=tradamerican"
      }
    ],
    "state": "CA",
    "review_count": 32,
    "distance": 1.87804019451141
  }
]

关于ruby - 我该如何改进?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3015972/

相关文章:

ruby - 为 Rails 中的 JSON 列中的键在模型上定义虚拟属性的正确方法

ruby-on-rails - 使用 FeedZirra 解析自定义提要元素

ruby - 如何使用 Ruby 连接到多个 WebSockets?

ruby-on-rails - 将 curl 命令转换为 httparty

ruby-on-rails - Ruby 2.0/Rails 4.0.0beta 升级在推送到 heroku 时失败

Ruby 不熟悉的字符串使用 Integer.chr 和 "\001"

ruby-on-rails - 在这种情况下我如何模拟一个对象?没有明显的方法可以用模拟替换对象

ruby-on-rails - 在 InheritedResources 上成功创建或更新操作后运行操作

javascript - Opal:Ruby 到 Javascript

Ruby 对象和模块