2017-05-05 280 views
0

我想按字母顺序排列字符串中的字母。按字母顺序排列字符串中的字母 - SAS

E.g.

'apple' = 'aelpp' 

我已经看到,有些类似的唯一功能是SORTC,但我想,以避免分裂每个字成书,如果可能的数组。

+0

有没有一个功能,只是这样做,如果这是你问。你有没有尝试过呢? – Joe

回答

2

乔的权利 - 没有这样做的内置函数。您可以在这里看到两个选项:

  1. 将字符串拆分为数组并使用call sortc对数组进行排序。您可以使用call pokelong非常轻松地完成此操作,前提是您首先定义了足够长度的数组。
  2. 实施您选择的sorting algorithm。如果您选择沿着这条路线走,我建议在=符号的左侧使用substr来更改单个字符,而不必重写整个字符串。

下面是一个如何做#1的例子。 #2将会有更多的工作。

data _null_; 
    myword = 'apple'; 
    array letters[5] $1; 
    call pokelong(myword,addrlong(letters1),5); /*Limit # of chars to copy to the length of array*/ 
    call sortc(of letters[*]); 
    myword = cat(of letters[*]); 
    putlog _all_; 
run; 

N.B.对于这里使用的长度为5的数组,请确保仅在使用call pokelong时才将字符串的前5个字符写入数组的起始处的内存中,以避免溢出超过数组的末尾 - 否则可以覆盖一些当处理更长的值myword时,其他任意部分的内存。这可能导致不希望的副作用,例如应用程序/系统崩溃。此外,用于填充数组的这种技术在SAS大学版中不起作用 - 如果您正在使用该技术,则需要使用do循环。

我对此进行了一些测试 - 排序长度为100的2m随机单词,包含从整个ASCII可打印范围中选择的字符,使用几年前PC的单个CPU花费大约15秒 - 时间少于它用来创建测试数据集。

data have; 
    length myword $100; 
    do i = 1 to 2000000; 
    do j = 1 to 100; 
     substr(myword,j,1) = byte(32 + int(ranuni(1) * (126 - 32))); 
    end; 
    output; 
    end; 
    drop i j; 
run; 

data want; 
    set have; 
    array letters[100] $1; 
    call pokelong(myword,addrlong(letters1),100); /*Limit # of chars to copy to the length of array*/ 
    call sortc(of letters[*]); 
    myword = cat(of letters[*]); 
    drop letters:; 
run; 
+0

你有什么想法#1会是多么昂贵?我有大约200万条记录。最终,我将使用第二个列表和[SPEDIS](http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000245949.htm)搜索最近的比赛。我知道这可能是做模糊匹配的一种奇怪的方式,但有一些突出的情况使我相信这是最好的方法。 –

+0

@JamesSteele增加了一项测试 - 限制因素(与SAS通常一样)似乎是磁盘I/O。 – user667489

+0

这是一个很好的解决方案,除了一件事:空白字符串中的空格。我会做两个更改:一个用于生成例程,一个用于WANT datastep。 – Joe