TypeError没有将Symbol隐式转换为Integer

时间:2018-08-27 17:47:35

标签: ruby-on-rails ruby

哈希

data = {
  :recordset => {
    :row => {
      :property => [
        {:name => "Code",     :value => "C0001"}, 
        {:name => "Customer", :value => "ROSSI MARIO"}
      ]
    }
  },
  :@xmlns => "http://localhost/test"
}

使用的代码

result = data[:recordset][:row].each_with_object([]) do |hash, out|
           out << hash[:property].each_with_object({}) do |h, o|
                    o[h[:name]] = h[:value]
                  end
         end

我无法获得以下输出:

[{"Code"=>"C0001", "Customer"=>"ROSSI MARIO", "Phone1"=>"1234567890"}

错误消息:

  

TypeError不能将Symbol隐式转换为Integer

在有多个记录的情况下可以正常工作

data = {
  :recordset => {
    :row => [{
      :property => [
        {:name => "Code",     :value => "C0001"},
        {:name => "Customer", :value => "ROSSI MARIO"},
        {:name => "Phone1",   :value => "1234567890"}
      ]
    }, {
      :property => [
        {:name => "Code",     :value => "C0002"},
        {:name => "Customer", :value => "VERDE VINCENT"},
        {:name => "Phone1",   :value => "9876543210"},
        {:name => "Phone2",   :value => "2468101214"}
      ]
    }]
  },
  :@xmlns => "http://localhost/test"
}

使用的代码

data.keys
#=> [:recordset, :@xmlns] 

data[:recordset][:row].count
#=> 2   # There are 2 set of attribute-value pairs


result = data[:recordset][:row].each_with_object([]) do |hash, out|
           out << hash[:property].each_with_object({}) do |h, o|
                    o[h[:name]] = h[:value]
                  end
         end
#=> [
#   {"Code"=>"C0001", "Customer"=>"ROSSI MARIO", "Phone1"=>"1234567890"},
#   {"Code"=>"C0002", "Customer"=>"VERDE VINCENT", "Phone1"=>"9876543210", "Phone2"=>"2468101214"}
# ] 

2 个答案:

答案 0 :(得分:5)

在第一种情况下,data[:recordset][:row]不是数组,而是哈希值,因此,当您对其进行迭代时,hash变量将成为数组:

[:property, [{:name=>"Code", :value=>"C0001"}, {:name=>"Customer", :value=>"ROSSI MARIO"}]]

在第二种情况下,它是一个数组,而不是哈希,所以当您对其进行迭代时,它将成为哈希:

{:property=>[{:name=>"Code", :value=>"C0001"}, {:name=>"Customer", :value=>"ROSSI MARIO"}, {:name=>"Phone1", :value=>"1234567890"}]}

您始终假定它是第二种格式。您可以将其强制为一个数组,然后将其展平1级以将两个实例视为相同:

result = [data[:recordset][:row]].flatten(1).each_with_object([]) do |hash, out|
  out << hash[:property].each_with_object({}) do |h, o|
    o[h[:name]] = h[:value]
  end
end

# => [{"Code"=>"C0001", "Customer"=>"ROSSI MARIO"}] # result from example 1
# => [{"Code"=>"C0001", "Customer"=>"ROSSI MARIO", "Phone1"=>"1234567890"},
#     {"Code"=>"C0002", "Customer"=>"VERDE VINCENT",
#      "Phone1"=>"9876543210", "Phone2"=>"2468101214"}] # result from example 2

尝试使用Kernal#Array()代替[].flatten(1)是很诱人的,但是您必须记住,Hash实现了to_a来返回嵌套的键和值数组,因此{{1} }无法像您希望的那样工作:

Kernal#Array()

答案 1 :(得分:0)

如果不是用于对输入进行规范化处理的数组,则可以创建一个数组。

public class NewAppWidget extends AppWidgetProvider {

    static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                                int appWidgetId) {

        CharSequence widgetText = context.getString(R.string.appwidget_text);
        // Construct the RemoteViews object
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);

        Intent intent = new Intent(context, MainActivity.class);
        PendingIntent pi = PendingIntent.getActivity(context, 0, intent, 0);

        views.setOnClickPendingIntent(R.id.red_button, pi);
        views.setTextViewText(R.id.red_button, widgetText);

        Bitmap icon = BitmapFactory.decodeResource(context.getResources(),
                R.drawable.button_default);

        views.setImageViewBitmap(R.id.red_button, icon);
        //views.setImageViewResource(R.id.red_button, R.drawable.button_default);


        // Instruct the widget manager to update the widget
        appWidgetManager.updateAppWidget(appWidgetId, views);
    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        // There may be multiple widgets active, so update all of them
        for (int appWidgetId : appWidgetIds) {
            updateAppWidget(context, appWidgetManager, appWidgetId);
        }

    }

    @Override
    public void onEnabled(Context context) {
        // Enter relevant functionality for when the first widget is created

    }

    @Override
    public void onDisabled(Context context) {
        // Enter relevant functionality for when the last widget is disabled
    }
}