在每个字符首次出现时拆分字符串


45

有关。

给定一个可打印的ASCII字符串,将其分割为一个非空字符串列表,并在每次出现以前从未在同一情况下出现过的字符时开始一个新的子字符串。

例子

"mississippi" → ["m","i","ssissi","ppi"]

"P P & C G" → ["P"," P ","& ","C ","G"]

"AAA" → ["AAA"]

"Adam" → ["A","d","a","m"]

"" → []


轶事:结果将包含0到95个元素。95 子串必然会一直持续到年底,因为在这一点上,所有可打印的ASCII字符已经开始子串,所以每一个额外的字符将之前发生,因而不能引起新的子字符串开始。


1
一个包含"'似乎是个好主意的示例。
Emigna

""[""]是否可以接受?
Arnauld

5
@Emigna只是弄乱了示例输出格式,没有进一步说明。
亚当

1
如果输出为以换行符分隔的字符串,是否可以使用前导/尾随换行符?
wastl

2
@wastl嗯,在这种情况下,我会允许使用它,因为它不能表示空段,尽管它确实与我先前的[""]无效裁决相冲突。叹。
亚当

Answers:


22

果冻,4字节

QƤĠị

在线尝试!

说明

QƤĠị  Input is a string, say s = "adam"
 Ƥ    For each prefix of s: ["a","ad","ada","adam"]
Q     remove duplicates: ["a","ad","ad","adm"]
  Ġ   Group indices by equal values: [[1],[2,3],[4]]
   ị  Index into s: ["a","da","m"]

TIO链接显示的字符串的内部表示形式略有不同。


10

视网膜,9字节

q1,`.
¶$&

在线尝试!

说明

匹配每个字符(.),丢弃重复的匹配项(q),丢弃第一个匹配项(1,),并在每个匹配项的前面插入换行符¶$&


6

05AB1E,11个字节

ÙSk¥sg¸«£õK

在线尝试!

说明

Ù             # remove duplicates in input
 S            # split to a list of characters
  k           # get the (first) index of each character in the input
   ¥          # calculate delta's
    sg¸«      # append the length of the input
        £     # split the list into pieces of these sizes
         õK   # remove empty string (for the special case "" -> [])

1
对于遇到此问题的任何人,¸«可以使用ª新版本的05AB1E。
Kevin Cruijssen

6

C, 75   65  63字节

感谢@Digital Trauma节省了10个字节,感谢@gastropner和@ l4m2分别节省了一个字节!

f(char*s){for(int l[128]={};*s;putchar(*s++))l[*s]++||puts(l);}

打印前导换行符。

在线尝试!

没有前导换行符(71个字节):

f(char*s){int l[128]={};for(l[*s]=1;*s;putchar(*s++))l[*s]++||puts(l);}

在线尝试!



@gastropner聪明的把戏;谢谢!
Steadybox

{0}=> {}
l4m2'3

@ l4m2是的,谢谢!
Steadybox'3

5

Perl 6的 58个52  40字节

{$/={};.comb.classify({$+=!$/{$_}++}).sort».value».join}

试试吧

*.comb.classify({$+=!(%){$_}++}).sort».value».join

试试吧

*.classify({$+=!(%){$_}++}).sort».value

试试看
(输入是字符列表,而输出是字符列表)

展开:

*                   # parameter for WhateverCode lambda

  .classify(        # classify that list
    {
        $           # anonymous scalar state variable (accumulator)

      +=            # increment it if:

        !           # Bool invert the following
          (
            %       # anonymous hash state variable
          ){ $_ }++ # look to see if the character was seen already
    }
  ).sort\           # sort the Pairs by key (makes the order correct)
  ».value           # get the value from each Pair

来自的输出classify

{ # Hash
  1 => ['m'],
  2 => ['i'],
  3 => ['s','s','i','s','s','i'],
  4 => ['p','p','i'],
}

并将.sort其变成:

[
  1 => ['m'],
  2 => ['i'],
  3 => ['s','s','i','s','s','i'],
  4 => ['p','p','i'],
]

».value 取出钥匙

[
  ['m'],
  ['i'],
  ['s','s','i','s','s','i'],
  ['p','p','i'],
]

为什么键会出故障?在Java中,插入顺序是基于内存还是插入顺序的,因此插入顺序是否不像Java中的a HashMap与a 一样被跟踪LinkedHashMap
魔术章鱼缸

1
@MagicOctopusUrn Perl的任何版本都没有订购哈希。实际上,Perl 5版本18使得哈希值更加随机化,这有助于减少某种类型的拒绝服务攻击的可能性,并且还导致错误的用户代码更频繁地暴露其错误行为。现在,某人可以(并且可能已经实现)了一个可以跟踪的类,但是要加载和使用这五个字符以上。
布拉德·吉尔伯特b2gills

5

J,7个字节

~:<;.1]

在线尝试!

说明

Nub筛子闪耀的机会!

~: <;.1 ]
        ]  Input
~:         Nub sieve (1 if the character is the first instance in string)
    ;.1    Split input on 1s in nub sieve
   <       And box each

2
我将要发布完全相同的答案(不足为奇),很高兴在此之前浏览了您的呈文:)
Galen Ivanov

2
@GalenIvanov我-我也想像其他大多数J高尔夫球手-享受使用裸筛或自我分类的机会。
科尔


5

05AB1E,8个字节

Ùvyy¶ì.;

在线尝试!


总会输出1个在前的换行符,它是常数,并不表示拆分,不输出在前的换行符的10字节替代方案是Ùvyy¶ì.;}¦,您可以在此处尝试。根据Adam的说法,前面或结尾的换行符都是可以接受的。


Input      = mississippi                               | Stack
-----------#-------------------------------------------+----------------------------------
Ù          # Push unique letters of first input.       | ['misp']
 v         # Iterate through each unique letter.       | []
  yy       # Push 2 copies of the letter (or yD)       | ['m','m']
    ¶      # Push a newline char.                      | ['m','m','\n']
     ì     # Prepended to the letter.                  | ['m','\nm']
      .;   # Replace first instance with '\n + letter' | ['\nmississippi']

每次迭代后,我们得到:

['\nmississippi'] > ['\nm\nississippi'] > ['\nm\ni\nssissippi'] > ['\nm\ni\nssissi\nppi']

这是:

m
i
ssissi
ppi

真好!击败我;)
艾米娜(Emigna

@Emigna这是对您的答案的评论,为期2天,然后我将其发布为b / c,没有回复哈哈:P。
魔术

很奇怪,还没有收到任何通知。足够不同的答案了:)
Emigna

@Emigna好吧,我是说,我删除了它哈哈。
魔术章鱼缸

跳过循环可节省一个字节ÙSD¶ì.;。不知道为什么我们以前没想到:P
艾米娜

5

Haskell,39个字节

foldl(\s c->s++['\n'|all(/=c)s]++[c])""

在线尝试!

在首次出现的每个字符之前插入一个换行符,从而导致一个以换行符分隔的字符串和一个换行符开头。预先lines.生成一个列表。


Haskell,55个字节

(""%)
_%[]=[]
p%s|(a,b)<-span(`elem`s!!0:p)s=a:(a++p)%b

在线尝试!

重复使用前缀第一个字符加上其后的非唯一字符。


@WheatWizard糟糕,是的lines
xnor

考虑到这一点tail.lines,可能想删除多余的空字符串。
小麦巫师

4

APL(Dyalog),9字节

谢谢,Outgolfer的Erik节省了1个字节!

⊢⊂⍨⍳∘≢∊⍳⍨

在线尝试!

说明:

⍳⍨:对于每个字符,获取其首次出现的索引。例如mississippi -> 1 2 3 3 2 3 3 2 9 9 2

⍳∘≢:从1到输入长度的范围。

:成员资格。例如1 2 3 4 5 6 7 8 9 10 11∊1 2 3 3 2 3 3 2 9 9 2 -> 1 1 1 0 0 0 0 0 1 0 0

⊢⊂⍨:使用1上述向量中以s 开头的新分区对输入字符串进行分区


9个字节(一元fg和一元f∘g行为相同)
埃里克Outgolfer

为什么要代替=
亚当

在撰写本文时,我还没有考虑到索引的位置正确。尽管很明显,他们是
H.PWiz

4

Japt,11个字节

‰ r@=iRUbY

在线测试!

说明

这是受Magic Octopus Urn05AB1E解决方案启发

‰ r@=iRUbY    Implicit: U = input string
‰             Split U into chars, and keep only the first occurrence of each.
   r@          Reduce; for each char Y in this string...
        UbY      Find the first index of Y in U.
      iR         Insert a newline at this index in U.
     =           Set U to the result.
               As reduce returns the result of the last function call, this gives the
               value of U after the final replacement, which is implicitly printed.

1
Japt在这里遇到了身份危机,由于某种原因,它称自己为Ruby。iRUbY
魔术章鱼缸

3

JavaScript(ES6),37个字节

保存7个字节:明确允许使用换行符(感谢@Shaggy!)

将输入作为字符数组。输出以换行符分隔的字符串。

s=>s.map(c=>s[c]=s[c]?c:`
`+c).join``

测试用例


允许使用换行符,因此您可以将其减少到37个字节
Shaggy

3

头脑操,66字节

,[>+[<[>+<<-<+>>-]>[>]<<[[+]++++++++++.>>>]<]<[>+<-]>>>[>>]<<-.>,]

格式:

,
[
  >+
  [
    <[>+< <-<+>>-]
    >[>]
    <<[[+]++++++++++.>>>]
    <
  ]
  <[>+<-]
  >>>[>>]
  <<-.>,
]

在线尝试

可以通过将xmain(最外面)循环的主体替换为来删除输出中的前导换行符(仅在输入为非空时打印),以5个字节为代价.>,[x]



2

K4,19个字节

解:

$[#x;(*:'.=x)_;,]x:

例子:

q)k)$[#x;(*:'.=x)_;,]x:"mississippi"
,"m"
,"i"
"ssissi"
"ppi"
q)k)$[#x;(*:'.=x)_;,]x:"P P & C G"
,"P"
" P "
"& "
"C "
,"G"
q)k)$[#x;(*:'.=x)_;,]x:"AAA"
"AAA"
q)k)$[#x;(*:'.=x)_;,]x:"Adam"
,"A"
,"d"
,"a"
,"m"
q)k)$[#x;(*:'.=x)_;,]x:""
,[""]

说明:

8个字节只是为了处理""...

$[#x;(*:'.=x)_;,]x: / the solution
                 x: / save input as variable x
$[  ;         ; ]   / $[condition;true;false]
  #x                / length of x ("" has length 0, i.e. false)
             _      / cut right at left indices
     (      )       / do together
          =x        / group x into key/value (char!indices)
         .          / return value (get indices)
      *:'           / first (*:) each
               ,    / enlist, "" => [""]

2

Python 2中81 74个字节

def f(s):d=sorted(map(s.find,set(s)));print map(lambda a,b:s[a:b],d,d[1:])

在线尝试!



@乔纳森·艾伦(JonathanAllan),这是一种误导性的副作用,set请不要保持秩序,要反驳->s='c'*6+'a'*100+'b'
Rod

我知道我们不能在将来的实现中依赖它,但我相信给定有序整数,由于整数是哈希值,我们会保持集合中的顺序(如您所展示的,对于其他对象而言,情况并非如此-您能找到吗?一个不适合我的替代词?)。
乔纳森·艾伦

@JonathanAllan 也不正确
Rod

嗯,很公平,我的信念是错误的!
乔纳森·艾伦


2

Perl,30个字节

包括+1用于p

输入时不要在STDIN上尾随换行符。输出也没有尾随换行符:

echo -n adam | perl -pE 's%.%$v{$&}+++!pos?$&:$/.$&%eg'; echo

如果你不关心开头和结尾的这个换行符25+3对于-p因为代码包含')也可以工作:

#!/usr/bin/perl -p
s%%$/x!$v{$'&~v0}++%eg

一如既往的好解决方案!根据提供的测试用例,您无需命名哈希,可以做到${$&}++。它不那么强大,但足以应付这个挑战吗?另外,关于meta的共识perl -p是不需要额外的字节,您只需要具有header即可,Perl with `-p` 而不仅仅是Perl。我想记住自己做的事
Dom Hastings '18

@DomHastings关于最多95个可能的字符串的注释非常有力地表明该字符串1是有效的,在这种情况下v需要使用该字符串。关于计数,我主要遵循codegolf.meta.stackexchange.com/a/7539/51507,对我而言,这是有关计数perl的最一致的元文章。
Ton Hospel '18

向大师学习总是很高兴。具体而言,在这种情况下,&~v0用于抓取第一个字符。感谢您加入本网站并分享您的长期专业知识。
msh210 '18

您可以使用Strawberry Perl,它"代替来'与一起使用-e,然后您可以将算作-ep+1而不是+3。(已测试。)
msh210 '18

2

JavaScript,61 54 52字节

将输入作为字符数组。

s=>s.map(x=>a[x]?a[y]+=x:a[x]=a[++y]=x,a=[],y=-1)&&a

试试吧

o.innerText=JSON.stringify((f=
s=>s.map(x=>a[x]?a[y]+=x:a[x]=a[++y]=x,a=[],y=-1)&&a
)([...i.value=""]));oninput=_=>o.innerText=JSON.stringify(f([...i.value]))
<input id=i><pre id=o></pre>


2

R94 87字节

function(s,n=nchar(s),g=substring)g(s,d<-which(!duplicated(g(s,1:n,1:n))),c(d[-1]-1,n))

在线尝试!

返回(可能为空)子字符串列表。

感谢Michael M节省了7个字节!


3
function(s,n=nchar(s),g=substring)g(s,d<-which(!duplicated(g(s,1:n,1:n))),c(d[-1]-1,n))会更短-当然有点丑...
Michael M

为什么要substring代替substr
plannapus

@MichaelM非常好!我仍然必须在其中添加if(n),因为substring对于空字符串输入会引发错误。
朱塞佩

1
@plannapus substr返回一个长度等于其第一个输入的向量,而substring返回一个长度等于其最长的输入的向量。
朱塞佩

@Giuseppe:在R 3.4.3中删除“ if(n)”会将空的输入字符串“”映射到空的输出字符串“”,这应该很好(?)
Michael M

2

Stax,8 个字节

ç↓‼►▐NVh

在线运行和调试

相同程序的ascii表示法是这样。

c{[Ii=}(m

对于每个字符,当当前字符的索引是当前位置时,它将拆分。

c            copy the input
 {    }(     split the string when the result of the enclosed block is truthy
  [          duplicate the input string under the top of the stack
   I         get the character index of the current character
    i=       is it equal to the iteration index?
        m    print each substring

2

> <>22 17 14字节

-1字节感谢Emigna

i:::a$1g?!o1po

在线尝试!

打印前导和尾随的换行符。

它通过p在第二行的相应位置上抽出该字符的副本并跟踪换行来跟踪已经出现的字母,如果从该位置获取的值不是1,则打印换行符。-1


大用g/p16个字节
Emigna


1

JavaScript(ES6),68个字节

s=>s.map(c=>o[c]?t+=c:(t&&m.push(t),t=o[c]=c),t='',o=m=[])&&[...m,t]

将输入作为字符列表。

测试用例:


我有一个类似的解决方案,问[""]最后一个测试用例是否可以接受。但这不是。:-(
Arnauld

哦,嗯,​​无论如何,您都有一个更好的解决方案:)
Rick Hitchcock

1

PHP,317字节

function SplitOnFirstUnique($s){
    $len = strlen($s); 
    $output = [];
    $newstring = '';
    for ($i=0; $i < $len ; $i++) { 
        $newstring = $newstring.$s[$i];
        if(!in_array($s[$i] , $output  )){
            $output[] = $newstring;
            $newstring = '';
        }
    }
    return $output;
}

在线尝试!


2
您好,欢迎来到PPCG!我已将您的帖子修改为我们的标准格式,并添加了“在线试用”链接,以便其他人可以测试您的代码。Code Golf的目的是编写尽可能短的代码,我可以看到几种使代码更短的方法,例如使用较短的变量名并保留一些空白。您可以查看常规技巧PHP技巧页面,以获取更多建议
不是一棵树

1

红色,79字节

func[s][foreach c next unique/case append s"^@"[print copy/part s s: find s c]]

在线尝试!

取消高尔夫:

f: func [s] [
    b: next unique/case append s "^@"  ; append `null` to the end of the string, than
                                       ; find the unique characters and 
                                       ; store all except the first to b  
    foreach c b [                      ; for each character in b
        print copy/part s s: find s c  ; print the part of the string to
                                       ; where the character is found and
                                       ; set the beginning of the string to that position
    ]
] 

1

SNOBOL4(CSNOBOL4)115 91 77字节

	N =INPUT
S	N LEN(1) . Y	:F(END)
	S =S Y
	N SPAN(S) . OUTPUT REM . N	:(S)
END

在线尝试!

打印用换行符分隔的子字符串。

说明:

S(for SPLIT)行实际上并未拆分,而是提取的第一个字符N并将其(.)保存到Y。在Failure,它跳转到END。匹配仅在N为空字符串时失败。因此,当输入为空时,它会直接跳转到END什么也不输出。

S = S Y连接YS

SPAN(S)贪婪地匹配中的一系列字符S,并将其(.)发送至OUTPUT,将(.)设置为()N的主要REM字符N。然后它跳回到S


1

PowerShell,73个字节

{$r=@();$h=@{};[char[]]$ARGS[0]|%{if(!($h[$_]++)){$r+=""};$r[-1]+=$_};$r}

用法

PS> & {$r=@();$h=@{};[char[]]$ARGS[0]|%{if(!($h[$_]++)){$r+=""};$r[-1]+=$_};$r} "mississipi" | ConvertTo-Json -Compress
["m","i","ssissi","pi"]

您可以保存一些字节- 在线尝试!
疯狂

1

红宝石65 62 58字节

->s,*a{s.size.times{|i|(i==s.index(c=s[i])?a:a[-1])<<c}
a}

在线尝试!

Lambda接受一个字符串并返回一个字符串数组。

方法:对于每个索引,请将该索引处的字符追加s到结果数组中,或追加到结果数组中的最后一个字符串。String#index返回参数的第一个实例的索引。

-2个字节:初始化a为splat参数,而不是单独一行。谢谢,超值墨水

-1字节:使用c=s[i]...... c不是s[i]...... s[i]谢谢,超值墨水

-4字节:.times代替.map



1

Java的8,193个 169 155 151字节

s->{for(int l=s.length(),i=0,j;i<l;i++)if(s.indexOf(s.charAt(i))==i){for(j=i;++j<l&&s.indexOf(s.charAt(j))!=j;);System.out.println(s.substring(i,j));}}

-14个字节感谢@raznagul(对于某些明显的我想念自己的事..)
-3字节感谢@OOBalance(同样对一些明显的我想念自己的事..:S)

说明:

在线尝试。

s->{                    // Method with String parameter and no return-type
  for(int l=s.length(), //  The length of the input-String
          i=0,j;        //  Index integers
      i<l;i++)          //  Loop `i` from 0 to `l` (exclusive)
    if(s.indexOf(s.charAt(i))==i){
                        //   If the character at index `i` hasn't occurred yet:
      for(j=i;++j<l     //    Inner loop `j` from `i` to `l` (exclusive),
          &&s.indexOf(s.charAt(j))!=j;);
                        //     as long as the character at index `j` has already occurred
      System.out.println(//    Print:
        s.substring(i,j));}}
                        //     The substring of the input from index `i` to `j` (exclusive)

1
我认为您不需要if(l<1)。如果l0循环不应该被执行反正为0<0false
raznagul

@raznagul不知道我是怎么想念它的,但是您说
得很

您要设置i=0两次。您可以通过删除第二个字节来节省3个字节:for(;i<l;i++)
OOBalance

@OOBalance不知道怎么回事..:S但感谢您的注意!:)
Kevin Cruijssen
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.