Как отсортировать вложенный массив объектов JSON в Ruby? - PullRequest
0 голосов
/ 10 сентября 2018

Доброе утро! У меня есть сложный набор данных для работы в Rails. Это массив массивов объектов JSON, каждый из которых имеет 4 атрибута. Пример ниже:

[
    [
        {
            "column_name": "ID",
            "column_id": "item_attributes#id",
            "column_value": "25295119-7113-42fe-90d5-394c7a841b31",
            "column_type": "string"
        },
        {
            "column_name": "Name",
            "column_id": "item_attributes#name",
            "column_value": "Webform submission",
            "column_type": "string"
        },
        {
            "column_name": "Current owner",
            "column_id": "item_attributes#current_owner",
            "column_value": "Joe Bloggs",
            "column_type": "string"
        },
        {
            "column_name": "State",
            "column_id": "item_attributes#state",
            "column_value": "New Task",
            "column_type": "string"
        },
        {
            "column_name": "Status",
            "column_id": "item_attributes#status",
            "column_value": "In progress",
            "column_type": "string"
        },
        {
            "column_name": "Created at",
            "column_id": "item_attributes#created_at",
            "column_value": "07/09/2018, 10:47 am",
            "column_type": "datetime"
        },
        {
            "column_name": "Updated at",
            "column_id": "item_attributes#updated_at",
            "column_value": "07/09/2018, 10:47 am",
            "column_type": "datetime"
        },
        {
            "column_name": "Task reviewer",
            "column_id": "item_participant_attributes#90a76abe-028f-45bc-8390-433bc39ba02e",
            "column_value": "Jane Bloggs",
            "column_type": "string"
        },
        {
            "column_name": "Task owner",
            "column_id": "item_participant_attributes#5bce3a02-07bf-4353-9f3d-2cc60f787584",
            "column_value": "Jack blogs",
            "column_type": "string"
        },
        {
            "column_name": "Make a list of your weekly tasks. Update status of this object to complete when it's complete.",
            "column_id": "element_attributes#533e26d8-c313-4d94-ab99-37263b0aa4ee",
            "column_value": null,
            "column_type": "string"
        },
        {
            "column_name": "Set target end date (choose Friday for end of this week)",
            "column_id": "element_attributes#6eeddd67-e1de-40c3-b220-197ddf554241",
            "column_value": null,
            "column_type": "datetime"
        },
        {
            "column_name": "Reviewer comments (optional)",
            "column_id": "element_attributes#3923358c-85f0-444b-9287-4738d9148eb9",
            "column_value": null,
            "column_type": "string"
        }
    ], 
    [...]
]

У меня есть модель с именем ReportTemplateColumn модель, которая определяет sort_priority и sort_direction, необходимые для каждого элемента, а также его значение column_id.

Мне нужно перебрать ReportTemplateColumns и применить их направление сортировки в порядке приоритета к набору данных, описанному выше.

Например, я знаю, что мне нужно переупорядочить набор данных на column_id = item_attributes#name в порядке desc. Массив массивов должен изменить порядок на основе значения column_value.

Моя попытка

  def set_sorted_data(data)
    @new_data = data
    self.report_template.report_template_columns.where('sort_priority != ?', 1000).order(:sort_priority).each do |report_template_column|
      @new_data = @new_data.sort_by { |x| x[0]["column_value"] }
    end
    return @new_data
  end

Ответы [ 2 ]

0 голосов
/ 10 сентября 2018

Работающая реализация приведена ниже, возможно, это не оптимально, но работает:

  def set_sorted_data(data)
    @new_data = data
    self.report_template.report_template_columns.where('sort_priority != ?', 1000).order(:sort_priority).reverse.each_with_index do |report_template_column|
      @new_data[0].each_with_index do |item_row_datum, index|
        if item_row_datum[:column_id] == report_template_column.column_id
          @index = index
        end
      end
      if report_template_column.column_type == 'number'
        @new_data.sort_by! { |item_row_datum| item_row_datum[@index][:column_value].to_i }
      elsif report_template_column.column_type == 'datetime'
        @new_data.sort_by! { |item_row_datum| item_row_datum[@index][:column_value].to_date }
      else
        @new_data.sort_by! { |item_row_datum| item_row_datum[@index][:column_value].to_s }
      end
      if report_template_column.sort_direction == 'desc'
        @new_data = @new_data.reverse
      end
    end
    return @new_data
  end
0 голосов
/ 10 сентября 2018

Я считаю, что .sort_by { |x| x[0]["column_value"] } - это главная проблема, например, если у вас есть что-то вроде этого.

f = [[{'a' => 4}, {'a' => 2}]]
# => [[{"a"=>4}, {"a"=>2}]]
f.sort_by{|d| d[0]['a']}
# => [[{"a"=>4}, {"a"=>2}]], won't change anything
f.first.sort_by{|d| d['a'] } # first represent the [0] here
# => [{"a"=>2}, {"a"=>4}], This gonna work

При использовании вашего подхода получилось что-то не так, то есть вы выполняете сортировку по внешнему массиву, делая, когда это так 1008 *, но указав, что ваша работа с внутренним массивом повлияет на внутренний массив, как в примере выше, надеюсь, он с вами работает.

Вы можете использовать sort_by! для сортировки на месте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...