【问题标题】:Sort letters in string alphabetically- SAS按字母顺序对字符串中的字母进行排序 - SAS
【发布时间】:2017-10-04 09:24:05
【问题描述】:

我想按字母顺序对字符串中的字母进行排序。

例如

'apple' = 'aelpp'

我见过的唯一有点相似的函数是SORTC,但如果可能的话,我想避免将每个单词拆分成一个字母数组。

【问题讨论】:

  • 没有一个功能可以做到这一点,如果那是你所要求的。你有没有尝试过这个?

标签: string sorting sas alphabetical


【解决方案1】:

Joe 是对的 - 没有内置函数可以做到这一点。我可以看到这里有两个选项:

  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;

注意对于此处使用的长度为 5 的数组,请确保在使用 call pokelong 时仅将字符串的前 5 个字符写入数组开头的内存,以避免溢出数组末尾 - 否则您可以在处理较长的 myword 值时覆盖内存的其他任意部分。这可能会导致不良副作用,例如应用程序/系统崩溃。此外,这种填充数组的技术在 SAS University Edition 中不起作用 - 如果您使用它,则需要使用 do-loop。

我对此做了一个小测试 - 使用几年前 PC 的单个 CPU 对 2m 个长度为 100 的随机单词进行排序,这些单词由从整个 ASCII 可打印范围中选择的字符组成,大约需要 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;

【讨论】:

  • 你知道#1 会有多贵吗?我有大约 200 万条记录。最终,我将使用第二个列表和SPEDIS 来搜索最接近的匹配项。我知道这可能是一种奇怪的模糊匹配方式,但有一些突出的情况让我相信这是最好的方法。
  • @JamesSteele 添加了一个测试 - 限制因素(就像 SAS 一样)似乎是磁盘 I/O。
  • 这是一个很好的解决方案,除了一件事:空白字符串中的空格。我会做两处改动:一处是生成例程,一处是 WANT 数据步。
  • 这里有一个生成器来缩短一些:data have; length myword $100; call streaminit(7); do i = 1 to 2000000; do j = 1 to 100; if rand('Uniform') < .05 and j > 5 then leave; substr(myword,j,1) = byte(32 + int(rand('Uniform') * (126 - 32))); end; output; call missing(myword); end; drop i j; run;
  • 这是我对 WANT 的建议修复。我认为还添加了临时数组 b/c 这就是您打算做的事情...(无法使代码格式正常工作-注意 _ 在字母 [ ] 调用中的临时和星号周围)`数据需要;设置有;数组字母[100] $1 临时;调用 pokelong(myword,addrlong(letters[1]),100);调用 sortc(字母[]); myword = left(cat(of letters[]));跑步; `
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-23
  • 1970-01-01
  • 1970-01-01
  • 2012-03-16
  • 2013-09-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多