Сначала я бы порекомендовал очистить имена файлов, разделив две части и, если возможно, удалив остальные:
- Разделите имена файлов по символу
'-'
или '_'
, чтобы сравнивать кортежи (стиль * цвет) вместо строк дважды. Также, если это вообще возможно, различайте при использовании цветового кода от имени цвета и разделяйте на 2 массива.
Теперь у вас есть 2 варианта: использовать словарь или отсортировать значения
- Словарь: возьмите более длинный список и поместите его в словарь. Сканируйте более короткий список в поисках значений. В словарях используются хеш-таблицы, которые делают их очень эффективными, а сравнения также очень быстрыми. Это требует, чтобы вы использовали в качестве ключа только стиль и цветовой код / имя, оставляя остальную часть строки вне.
Решение может выглядеть так:
let dict () =
let dict = new Dictionary<_, _>()
allFiles |> Seq.iter (fun f -> f.Filename.Split '-' |> fun a -> dict.Add((a.[0], a.[1]), f) )
products
|> Array.Parallel.map (fun p ->
let vRef = ref { Filename = "" }
if dict.TryGetValue((p.Style, p.ColorCode) , vRef)
then {p with Filename = (!vRef).Filename }
else p
)
Если это невозможно, подумайте:
- Сортировка обоих списков: продукты и имена файлов. Сканируйте оба упорядоченных списка одновременно с индексом, каждый раз увеличивая только нижнее значение.
Еще одна вещь:
Если вы все еще хотите проводить сравнения строк, вы должны рассмотреть возможность использования скомпилированного Regex, который очень эффективен. Ваше регулярное выражение может быть чем-то вроде: ^code[-_](red|FF0000)
, которое будет соответствовать любому из 4 значений:
code-red
code_red
code-FF0000
code_FF0000
Вот как вы используете скомпилированное регулярное выражение:
let regex = new Regex(sprintf "^%s[-_](%s|%s)" p.Style p.ColorCode p.ColorName, RegexOptions.Singleline + RegexOptions.Compiled)
for i in 1..30 do
if regex.IsMatch(sprintf "code-%d" i) then printfn "%A" i