简体   繁体   中英

Finding occurrences in a string and retaining the order of occurrence

I've been using regex to finding different patterns in a string, which works alright, but I am losing the order of occurrence.

For example, when I am checking this string: 10£ + 5$ / 4EUR , I would check if there are symbols and/or ISO codes and do some extra work on the side, which ultimately returns an array. But it's not sorted by occurrences

Main method which finds all currencies

def find_currencies(string)
  currencies = []

  # check symbols
  currencies = currencies + currencies_from_symbol(string) if string =~ /\p{Sc}/
  # check iso codes
  if Currency.iso_codes.any? { |code| string =~ /#{code}/i }
    iso_codes = string.scan(Regexp.new(Currency.iso_codes.join('|'), true))

    currencies = currencies + iso_codes.map { |code| Money::Currency.find(code.downcase.to_sym) }
  end

  currencies
end

Method to return currencies from a currency symbol

def currencies_from_symbol(string)
  currencies = Money::Currency.all.select do |m|
    string.scan(/\p{Sc}/).include?(m.symbol) && m.priority < 10
  end

  unless currencies.any? { |m| m.id == :usd || m.id == :gbp }
    return currencies
  end

  # Default to USD and GBP
  # TODO: Remove when default can be selected
  currencies.select { |m| m.id == :usd || m.id == :gbp }
end

find_currencies will returns, for example: [#<Money::Currency id: usd>, #<Money::Currency id: gbp>, #<Money::Currency id: eur>] , which doesn't correspond to the string original order. I need it to be [gbp, usd, eur]

I would really appreciate help on this. My current thinking that I need to do a lookup for symbols and iso codes at the same time to retain occurrence order somehow. But doing it separately would be better of course.

I've adopted an approach suggested by @kiddorails, which seems to work so far. I've also split out some methods, but using all currency symbols and doing a direct select ended up retaining the right order:

symbols    = string.scan(/\p{Sc}/)
currencies = symbols.flat_map { |symbol| find_currency_by_symbol(symbol) }

def find_currency_by_symbol(symbol)
  Money::Currency.all.select do |currency|
    currency.symbol == symbol && currency.priority < 10
  end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM