Julia:通过子字符串包含对字符串数组进行排序

时间:2017-07-10 13:57:04

标签: julia

我有一些非常难看的代码来排序包含几个月子串的字符串数组。

所以给出:

months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]
test = ["xxxFebxxx","xxxJanxxx","xxxAprxxx"]

function sortf(s)
    ix = 0
    for m in months
        if contains(s,m)==true
            return ix
        end
        ix = ix + 1
    end
    return size(months)[1] # in case substring not found
end

sort!(test,by=sortf)

# result should be ["xxxJanxxx","xxxFebxxx","xxxAprxxx"]

通过在几个月内检查子字符串,简洁的Julia是如何排序测试的?

2 个答案:

答案 0 :(得分:2)

简洁的单行将是:

sort!(test,by=t->first(filter(x->contains(t,x[2]),enumerate([months;""])))[1])

使用的功能:

  • [months;""]months的末尾添加一个虚拟字符串,以重现将没有月子字符串的测试字符串移动到列表末尾。

  • enumerate( )每月都会附上一个号码,以供sort!使用。

  • filter( )查看(数字,月份)对的集合,并在字符串中搜索数月。 单独恼人filter可能会生成警告,可以将其替换为Iterators.filter以避免

  • first( )[1]获取第一个(数字,月份)对,停止filter并返回月份数。

  • sort!( ,by= )与相关行类似。

这执行与问题中相同的计算,并且还保持问题中代码的效率,该代码明确地使月搜索短路并且不会产生太多的中间变量。

另一条路线(来自@AlexanderMorley)将创建测试字符串x月搜索矩阵。这很浪费,但编译器很容易实现,所以它仍然很快:

test[
  sortperm(vec(mapslices(findfirst,contains.(test,reshape([months;""],1,:)),2)))
]

答案 1 :(得分:1)

可以使用点广播来获得这种单行。对我来说它很可读,但肯定不会非常有效。

test[sortperm(findfirst.([contains.(x, [months; ""]) for x in test]), by=x->x[1])]

编辑

以反映@ DanGetz的评论

相关问题