Julia:按子字符串包含对字符串数组排序

Julia:按子字符串包含对字符串数组排序,julia,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

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

因此:

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"]

通过在几个月内检查子字符串对测试进行排序的简洁方法是什么?

简洁的一行是:

sort!(test,by=t->first(filter(x->contains(t,x[2]),enumerate([months;""])))[1])
使用的功能:

  • [months;“”]
    月底添加一个伪字符串
    以复制将没有月子字符串的测试字符串移动到列表末尾的过程

  • enumerate()
    为每个月添加一个数字,以提取供
    排序使用

  • filter()
    检查(数字、月份)对的集合,并在字符串中搜索月份。恼人的是,
    filter
    本身可能会生成警告,并且可以用
    迭代器替换。filter
    可以避免它

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

  • 排序!(,by=)
    类似于所讨论的行

这将执行与问题中相同的计算,并保持问题中代码的效率,该代码显式地缩短了月份搜索,并且不会创建太多中间变量

另一种方法(êla@AlexanderMorley)是创建teststring x month搜索矩阵。这是一种浪费,但编译器很容易实现,因此速度仍然很快:

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

可以使用点广播来获得这一行。对我来说,这本书可读性很强,但肯定不会很有效率

test[sortperm(findfirst.([contains.(x,[months;“”))表示测试中的x]),by=x->x[1])


使用
findfirst
编辑以反映@DanGetz的评论在这里更好。此外,将
months
替换为
[months;“”]
不会复制问题中的月份字符串行为谢谢,必须将筛选器替换为迭代器。中不推荐使用筛选器作为筛选器。6