сортировка по ruby ​​для изменения порядка элементов массива с использованием другого массива - PullRequest
1 голос
/ 07 июня 2019

Я ищу оптимальный способ использовать один массив для сортировки другого.Код ниже работает, но с низкой производительностью, потому что это O (n ^ 2).

re_ordered_array = []

use_for_ordering = ["title", "creator", 'alternate_identifier', "keyword"]

array_to_reorder = ["keyword_1", "title", "creator_1", "keyword_2", "creator_2", 'alternate_identifier']

use_for_ordering.each do |value|  
  re_ordered_array << array_to_reorder.select {|r| r =~ /#{value}/} 
end

В результате вышеизложенного будет возвращен новый упорядоченный массив:

re_ordered_array.flatten.compact

["title", "creator_1", "creator_2", "alternate_identifier", "keyword_1", "keyword_2"]

Чтобы улучшить порядок перекомпоновки / обработки ключей, я попробовал следующий подход

hash = use_for_ordering.each_with_index.to_h

Вышеприведенный хеш распечатывает

    {"title"=>0, "creator"=>1, "alternate_identifier"=>2, "keyword"=>3}

, который я затем использую здесь при повторной сортировке ниже

array_to_reorder.sort.each do |k| 
   use_for_ordering.any? do |i| 
     re_ordered_array.insert(hash[i], k) if  k =~ /#{i}/  
  end
end

В результате получается

 re_ordered_array.compact

который дает

 ["title", "creator_2", "creator_1", "keyword_2", "keyword_1", "alternate_identifier"]

Проблема с новым массивом состоит в том, что creator_1 должен быть перед creator_2, то же самое относится и к keyword_1 и keyword_2

, но конечный результат того, что я хочу, нижено без O (n ^ 2) или многократного обращения к массиву

 ["title", "creator_1", "creator_2", "alternate_identifier", "keyword_1", "keyword_2"]

обновленный массив с улучшенными репрезентативными данными

 representative_array_order =  ["id", "date_uploaded", "date_modified", "file_url", "visibility", "embargo_end_date", "visibility_after_embargo", "lease_end_date", "visibility_after_lease", "collection", "work_type", "resource_type", "title", "creator", "contributor", "doi", "alternate_identifier", "version", "related_identifier", "series_name", "volume", "edition", "journal_title", "book_title", "issue", "pagination", "editor", "publisher", "place_of_publication", "isbn", "issn", "eissn", "article_number", "material_media", "date_published", "date_accepted", "date_submitted", "abstract", "keyword", "institution", "organisational_unit", "peer_reviewed", "official_url", "related_url", "related_exhibition", "related_exhibition_date", "project_name", "funder", "funder_project_reference", "additional_information", "license", "rights_statement", "rights_holder", "language", "event_title", "event_date", "event_location"]

 representative_array_for_recorder = ["file_1", "id", "title_1", "date_uploaded", "date_modified", "account_cname", "institution_1", "institution_2", "institution_3", "institution_4", "institution_5", "funder_1", "funder_2", "date_published", "date_accepted", "date_submitted", "project_name_1", "project_name_2", "rights_holder_1", "rights_holder_2", "doi", "place_of_publication_1", "place_of_publication_2", "abstract", "alternate_identifier_1", "alternate_identifier_type_1", "alternate_identifier_2", "alternate_identifier_type_2", "alternate_identifier_3", "alternate_identifier_type_3", "related_identifier_type_1", "related_identifier_id_1", "related_identifier_relationship_1", "related_identifier_type_2", "related_identifier_id_2", "related_identifier_relationship_2", "library_of_congress_classification_1", "library_of_congress_classification_2", "alt_title_1", "alt_title_2", "volume_1", "pagination", "issn", "eissn", "edition", "event_title", "event_date", "event_location", "book_title", "journal_title", "issue", "isbn", "related_exhibition", "related_exhibition_date", "version", "alternative_journal_title_1", "alternative_journal_title_2", "resource_type_1", "creator_family_name_1", "creator_name_type_1", "creator_orcid_1", "creator_isni_1", "creator_position_1", "creator_given_name_2", "creator_family_name_2", "creator_name_type_2", "creator_orcid_2", "creator_isni_2", "creator_position_2", "creator_name_type_3", "creator_isni_3", "creator_position_3", "creator_organisation_name_3", "contributor_given_name_1", "contributor_family_name_1", "contributor_name_type_1", "contributor_orcid_1", "contributor_isni_1", "contributor_position_1", "contributor_name_type_2", "contributor_isni_2", "contributor_position_2", "contributor_organisation_name_2", "description", "keyword_1", "keyword_2", "keyword_3", "license_1", "license_2", "rights_statement_1", "publisher_1", "date_created", "subject", "language", "related_url_1", "related_url_2", "source", "embargo_end_date", "lease_end_date", "visibility", "visibility_after_embargo", "work_type", "visibility_after_lease", "collection", "organisation_unit_1", "organisation_unit_2", "peer_reviewed", "funder_project_reference_1", "funder_project_reference_2", "additional_information", "official_url", "article_number", "material_media"]

Ответы [ 2 ]

1 голос
/ 07 июня 2019

Я могу предложить эту опцию:

Настройка

array_to_reorder = use_for_ordering.each_with_object({}) { |k, h| h[k] =  array_to_reorder.select { |e| e.start_with? k } }
#=> {"title"=>["title"], "creator"=>["creator_1", "creator_2"], "alternate_identifier"=>["alternate_identifier"], "keyword"=>["keyword_1", "keyword_2"]}
use_for_ordering = use_for_ordering.map.zip(0..).to_h
#=> {"title"=>0, "creator"=>1, "alternate_identifier"=>2, "keyword"=>3}

При необходимости вы можете отсортировать значения array_to_reorder перед следующим шагом.

Сортировка

array_to_reorder.sort_by { |k, _| use_for_ordering[k] }.flat_map(&:last)
#=> ["title", "creator_1", "creator_2", "alternate_identifier", "keyword_1", "keyword_2"]
1 голос
/ 07 июня 2019

Вы, вероятно, хотите подготовить массив регулярных выражений заранее, вместо того, чтобы создавать их из строк в начале каждой итерации.

use_for_ordering = 
  %w[title creator alternate_identifier keyword].
    map(&Regexp.method(:new))
#⇒ [/title/, /creator/, /alternate_identifier/, /keyword/]

Или, что еще лучше, создайте перечислитель:

use_for_ordering = 
  %w[title creator alternate_identifier keyword].
    map(&Regexp.method(:new)).each_with_index
#⇒ #<Enumerator: ...>

Теперь вы можете группировать значения и затем сортировать по индексу:

array_to_reorder.
  group_by do |e|
    key = use_for_ordering.find { |r, i| r =~ e  }
    key.nil? ? Float::INFINITY : key.last
  end.sort.flat_map(&:last)
#⇒ ["title", "creator_1", "creator_2",
#   "alternate_identifier", "keyword_1", "keyword_2"]
...