URL友好的标题


28

这个网站上的人们真的很喜欢修饰自己的帖子标题...

Stewie's sequence: + * - / + * - /

但是,当此标题需要包含在页面URL中时,它可以简化:

stewies-sequence

挑战

您的任务是创建一个程序或函数,给定代表帖子标题的字符串,该程序或函数将输出/返回其“ URL友好”转换。

该算法是:

  • 转换为小写字母(如果适用)
  • 用破折号()替换每个空格(),句点(.),逗号(,)或斜杠/-
  • 删除所有非字母数字字符,破折号除外。
  • 缩小相邻破折号(a---b -> a-b)的组,删除所有前导/尾随的破折号。

请注意,此算法只是一种简化,可能不会总是产生与该站点的真实方法相同的结果。


规则

  • 您可以假设输入:
    • 不会为空。
    • 将至少包含一个字母数字字符。
    • 仅包含ASCII范围32-126中的字符(可打印)
  • 允许使用完整的程序或功能。
  • 这不准确的任务说明一个内置的是不是允许的。
  • 这是,因此最短的解决方案(以字节为单位)获胜!

测试用例

该网站上的大多数帖子都将用作测试,但这是一个方便的列表:

Loading... Forever       -> loading-forever
N(e(s(t))) a string      -> nest-a-string
"Hello, World!"          -> hello-world
URL-Friendly titles      -> url-friendly-titles

C.U.S.R.S                -> c-u-s-r-s
1+2+3+4+...+n = -1/12?   -> 1234-n-1-12
How can I use cmp(a,b)   -> how-can-i-use-cmpa-b

一些更长的...

Export The $PATH Variable, Line-By-Line   -> export-the-path-variable-line-by-line
Do n and n^3 have the same set of digits? -> do-n-and-n3-have-the-same-set-of-digits
Quine Anagrams! (Cops' Thread)            -> quine-anagrams-cops-thread
The Golfer Adventure - Chapter 1          -> the-golfer-adventure-chapter-1
Bootloader golf: Brainf***                -> bootloader-golf-brainf

以及一些边缘情况检查样本(随意建议更多):

0123   ->   0123
a a1   ->   a-a1
2-1=1  ->   2-11

那前导-s呢?是否必须将其删除?例如,在中asdf-,是否-必须删除最后一个?
Kritixi Lithos

我们可以使用内置函数来检查字符是否为字母数字吗if(isalphanum(ch))...
Mukul Kumar

1
@KritixiLithos 最小化相邻破折号的组(a --- b-> ab),删除所有前导/尾随的破折号我想这应该使您清楚。
Mukul Kumar

又是怎么回事_下划线?我的代码有效,除非有下划线。
Kritixi Lithos

@ L3viathan现在不要紧了,我更改了代码,以便甚至删除了下划线
Kritixi Lithos

Answers:


7

视网膜,33 31字节

T`L`l
[^a-z ,-9]+

\W+
-
^-|-$

(程序末尾有换行符)

我不确定我可以从中得到更多的帮助。这应该涵盖了所有内容。类似于妈妈趣味卷。使用递归正则表达式的另一个33字节版本

在线尝试!

说明

T`L`l

这条线是简单,将其转换通过为小写Ť ransliterating A-ZL)到a-zl,小写)。


这个阶段很简单,它基本上消除了所有不需要的字符,以免以后给自己带来很多麻烦

[^a-z ,-9]+

[^a-z ,-9] 匹配任何非以下字符:

  • a-z:小写字母(由于前一项,请记住整个字符串都是小写)
  • :空间字符
  • ,-9这是字符代码范围,,以9这恰好是,-./0123456789,正是我们所需要的字符

接下来,我们将所有非字母数字字符转换为破折号(现在为just ,./-

\W+
-

这将(不)匹配(否定)中_包含的匹配项,因为在上一阶段已将其删除\w\W


我认为这对于诸如的输入将失败a = b
Martin Ender

我真的很想接受这一点,但是正如马丁所说,当您输入a = b:(
FlipTack

@ Flp.Tkc很抱歉回复迟到(现在是决赛周)。我设法挤出另外两个字节修复它。我认为这现在可以正确处理此类情况
Downgoat

9

JavaScript(ES6),90 82 79 75字节

这是一次尝试完成一项任务的尝试replace()。此代码仅提取我们感兴趣的字符,而忽略其他所有内容。还有一些其他逻辑可以处理连字符。

s=>(s.toLowerCase().replace(/[ a-z,-9]/g,c=>S=c<'0'?s+'-':s=s?S+c:c,s=0),s)

测试用例


1
对于,a^a,,此代码给出了-aa-(有前导/后缀连字符)
Kritixi Lithos

@KritixiLithos哦,感谢您指出这一点。我没有注意那个规则。应该解决。
Arnauld

9

V41,40,37,36字节

VuÍ[ .,\/]/-
Í0-9a-z­]
Í-«/-
Í^-ü-$

在线尝试!一次检查所有测试用例!

与往常一样,这里包含一堆不可打印的非ASCII字符,因此这是一个十六进制转储:

0000000: 5675 cd5b 202e 2c5c 2f5d 2f2d 0acd 8430  Vu.[ .,\/]/-...0
0000010: 2d39 612d 7aad 5d0a cd2d ab2f 2d0a cd5e  -9a-z.]..-./-..^
0000020: 2dfc 2d24                                -.-$

在V的“压缩正则表达式”系统派上用场时,正是这些挑战。

说明

首先,我们将所有内容都转换为小写。幸运的是,有一个非常方便的方法可以做到两个字节。我在这里写了一个小贴士。所以我们做

V           " Visually select this whole line
 u          " Convert this whole line to lowercase

之后,我们执行了一系列压缩的替代命令。这里可以很好地了解V的压缩正则表达式的工作原理,但是基本思想是我们可以设置高位以避免逃脱某些字符。另一个方便之处是可以自动填充范围(如:%)和标志(如/g)。但是最后,它们全部转换为vim替代命令。实际上,我们甚至可以将程序的其余部分直接转换为vim。那会给我们这个:

:%s/[ .,/]/-/g
:%s/[^0-9a-z\-]//g
:%s/-\+/-
:%s/^-\|-$//g

如果您说的是vim-regex,则应该更清楚程序其余部分现在做什么。这是程序的其余部分:

Í               " Substitute:
 [ .,\/]        "   a space, period, comma or forward slash. (Due to a strange bug, this needs to be escaped)
        /-      "   with a dash
Í               " Remove:
 [^0-9a-z­]     "   Any character that is not a dash or alpha-numeric
Í               " Substitute:
 -«             "   One or more dashes
   /-           "   with one dash
Í               " Remove:
 ^-             "   A dash at the beginning of a line
   ü            "   OR
    -$          "   a dash at the end of a line

8

JavaScript(ES6)91 96

@ETHproductions 保存了1个字节

s=>s.toLowerCase().replace(/([ .,/-])|\W|_/g,(c,d)=>d?'-':'').replace(/^-*|-*$|-(?=-)/g,'')

测试

F=
s=>s.toLowerCase().replace(/([ .,/-])|\W|_/g,(c,d)=>d?'-':'').replace(/^-*|-*$|-(?=-)/g,'')

;[['Loading... Forever.....', 'loading-forever'],
['N(e(s(t))) a string', 'nest-a-string'],
['"Hello, World!"', 'hello-world'],
['URL-Friendly titles', 'url-friendly-titles'],
['C.U.S.R.S','c-u-s-r-s'],
['1+2+3+4+...+n = -1/12?', '1234-n-1-12'],
['How can I use cmp(a,b)', 'how-can-i-use-cmpa-b'],
['Export The $PATH Variable, Line-By-Line', 'export-the-path-variable-line-by-line'],
['Do n and n^3 have the same set of digits?', 'do-n-and-n3-have-the-same-set-of-digits'],
['Quine Anagrams! (Cops\' Thread)', 'quine-anagrams-cops-thread'],
['The Golfer Adventure - Chapter 1', 'the-golfer-adventure-chapter-1'],
['Bootloader golf: Brainf***', 'bootloader-golf-brainf'],
['0123', '0123'],
['a a1', 'a-a1'],
['2-1=1', '2-11']]
.forEach(t=>{
  var i=t[0],k=t[1],r=F(i)
  console.log(r==k?'OK':'KO',i+' -> '+r,r==k?'':k)
})


这有完全相同的BYTECOUNT我的答案,如果将它转换成一个命名函数
Kritixi LITHOS

不要以为您不需要最后*一个正则表达式中的最后一个,尽管我可能错了
ETHproductions 2016年

我可能会误会,但是您确定提前行是必要的吗?
Kritixi Lithos

@KritixiLithos先行必须保持至少1 -串内,而在开始和结束删除所有
edc65

@ETHproductions正确,谢谢
edc65 '16

4

Python 3中,103个 100 96 95字节

Flp.Tkc节省了5个字节

import re
lambda s,y=re.sub,d='-':y('-+',d,y('[^0-9a-z-]','',y('[ .,/]',d,s.lower()))).strip(d)

@ Flp.Tkc确实..
L3viathan

糟糕,我无意中对此表示反对。除非您编辑此帖子
否则

@KritixiLithos完成
L3viathan


3

MATL,38字节

'-'jyvk45y' .,/'m(t8Y245hm)'-*'45YX6L)

在线尝试!验证所有测试用例

说明

'-'jyv       % Take input line. Append and prepend a dash. Gives a char column vector
k            % Convert to lowercase
45y' .,/'m(  % Replace any of ' .,/' by a dash, using assignment indexing
t8Y245hm)    % Keep only alphanumeric chars or dashes, using reference indexing
'-*'45YX     % Replace each run of dashes by a single dash, using a regular expression
6L)          % Remove first and last chars, which are always dashes. Implicitly display

3

Ruby61 60 61 64 53字节

(52个字节的代码加上的一个字节-p

$_=$_.tr("A-Z ,-/","a-z ").gsub(/[^\w ]/){}.split*?-

在线尝试!

tr()–转换大写字符,空格,逗号,句号和斜杠。暂时-用空格代替,以便strip以后使用。
请注意,表达式中的-字符"A-Z ,-/"实际上是一个范围运算符,这也使该.字符易于转换。这种操作实际上并不会减少字节数,但是很不错,因此可以保留下来。

gsub(/[^\w ]/){} –删除所有不在允许集中的字符。

split–从技术上讲,我们并不完全需要该数组,而是split消除了开头和结尾的空格(实际上-是变相的字符)。作为奖励,这将多个空间挤在一起。

*?-–的简写.join("-");这同时颠倒了前面的split操作空白转换。使用字符文字缩写表示法可以节省一个字节,这使得程序需要Ruby 1.9或更高版本。

更新1: 使用gets而不是Ruby的流编辑模式可以节省一个字节。
根据ValueInk的建议恢复

更新2 :( 总共+3个字节)

  • 固定大小写..--hi, $/(→ hi(+10字节) –再次由用户ValueInk提供
  • 恶意-p (+1字节)
  • 摆脱squeezegsub改用了(+2个字节),这使我能够:
  • 使用strip处理开头和结尾的破折号(-10字节)

更新3: ValueInk的Hattrick。通过利用String#split自动挤压同一分隔符的习惯,我们节省了11个字节,这使我们可以抛弃整个final strip/ gsub链,并用split/ join组合替换。(-11个字节)


这仅在REPL环境中返回字符串,并且如果以正确的Ruby程序运行则失败,这是不好的。仅完整程序或功能/ lambda。实际上,您的旧版本可以使用该-p标志,但是绝对不能。
价值墨水

@ValueInk您当然是正确的。我已经相应地更改了解决方案。谢谢你的评论; 这正是我非常感谢的指导,因为这是我第一次打高尔夫球。
Synoli

1
感谢您进行修复;我删除了我的下注。需要注意的是,使用该-p标志会隐式地向您的代码添加1个字节(因为它会将您的代码执行从更改ruby -e 'your code'ruby -pe 'your code')。我还发现了一种边缘情况,它可以提供-hi-输入,例如..--hi, $/当您应该删除所有前导/尾随破折号并因此而返回时hi
价值墨水

2
通过更改gsub(/[^\w ]/){}为-2个字节tr('^a-z ',''),然后以结尾,.split*?-而不是结尾,.strip.gsub...因为它可以自动处理重复项字符串的结尾,所有操作都是一次完成!
价值墨水

1
既然没有人说过,欢迎来到代码高尔夫!
FlipTack

3

JavaScript(ES6),74 69字节

f=
s=>s.toLowerCase().replace(/[^-/,. a-z\d]/g,``).match(/\w+/g).join`-`
<input oninput=o.textContent=/[a-z\d]/i.test(this.value)?f(this.value):``><pre id=o>

编辑:通过意识到我已经删除了所有字符,节省了5个字节,-/,. 0-9a-z所以我可以使用它\w来匹配其余的单词。


我认为您必须将HTML代码包含在字节数中,因为它已用于解决挑战
Kritixi Lithos

1
@KritixiLithos不,它仅用于演示目的。问题是我的代码可以假定至少一个字母数字字符,而HTML代码在调用该函数之前只是对其进行了测试。
尼尔

[a-z\d]可以[^\W_]吗?
edc65 '16

@ edc65不错,但是后来我意识到这可能更简单!
尼尔

2

PHP,87字节

正则表达式的思想来自现有的答案。

<?=trim(preg_replace(['@[^ a-z,-9]@','@[ ,-/]+@'],['','-'],strtolower($_GET[T])),'-');

它要求您有一台运行PHP的服务器,并通过HTTP访问。

标题必须在键上T,并且结果将打印在屏幕上。

例: http://localhost/title.php?T=<my shiny title>


2

bash / Unix工具,56字节

tr A-Z\ .,/ a-z-|tr -cds a-z0-9- -|sed s/^-//|sed s/-$//

将大写字母替换为小写字母,并将所需的特殊字符替换为破折号。

删除字母,数字和破折号以外的字符(tr的-d选项),然后将一行中的多个破折号(tr的-s选项)挤压成一个破折号。

在开头,然后在结尾处删除破折号。


2

Powershell,85字节

($args[0].ToLower()-replace'[ .,/]','-'-replace'[^a-z,-9]'-replace'-+','-').Trim('-')

将其设为小写,然后将3个正则表达式替换为一行,并修剪所有尾随-


可能不会为$input您节省2个字节?
briantist '16

2

JavaScript中,90个 98 94 93 91 90 91字节

@ edc65节省了1个字节!

感谢@IsmaelMiguel找到领先的分号,节省了1个字节!

失败后获得1个字节 ,a-^-a,

f=s=>s.toLowerCase().replace(/[^ a-z,-9]/g,"").replace(/[ ,-/]+/g,"-").replace(/^-|-$/g,"")

我最喜欢这个特定提交的东西是范围。在第一个replace,我们会删除任何不是字母,而不是一个,-./而不是空间。我们a-z用于检测字母,并且,-9用于检测那些特殊字符数字,因为这些ASCII文字的字符代码全部对齐!

, = 44
- = 45
. = 46
/ = 47
0 = 48
...
9 = 57


不删除前导破折号:“-1”变成“ -1”,而应变成“ 1”。
L3viathan

@ L3viathan现在应该工作
Kritixi Lithos 16/12/10

无需计数,f=因此您的字节数现在为96。并且不需要\在正则表达式的范围内,因此它可以是95。但是...仍然不起作用:尝试...title
edc65

1
嘿!我没有那么老!(65不是64)
edc65 '16

1
我相信您并不需要最后的f=;。只需指定这是一个匿名函数即可。这样,您的答案应为90个字节长。
伊斯梅尔·米格尔

1

Lua,91个字节

a=a:lower():gsub( '[ .,/]', '-' ):gsub( '[^%w-]', '' ):gsub( '%-+', '-' ):match'%-?(.*)%-?'

aURL字符串在哪里。

说明:

  • 大多数都非常简单。a:lower()返回小写函数
  • :gsub 查找模式的匹配项,并将其替换为字符串。
  • '[ .,/]':方括号的意思是“或”,因此它与空格,句点,逗号和斜杠匹配。不必贪婪,因为:gsub所有情况都会发生。
  • '[^%w-]'^放在方括号中时表示“不是”,%w表示字母数字。所以'[^%w-]匹配任何不是的东西字母数字或破折号的字符。
  • '%-+':尽可能多地匹配破折号,并仅用一个破折号代替它们。
  • match'%-?(.*)%-?':在Lua中,如果字符串是函数的唯一参数,则不需要括号。只需要在开头和结尾检查一个破折号,因为破折号已经被最小化了。不需要锚字符,因为它.*可以匹配所有内容,贪婪。

1

C,194字节

i,j;f(char*s,char*d){if(*s>47&*s<58|*s>96&*s<123)d[i++]=*s;if(*s>64&*s<91)d[i++]=*s+32;if(i-j&&*s>43&*s<48|*s==32&&*(s+1)&&*(s+1)>47|(*(s+1)<44&&*(s+1)^32)){d[i++]=45;j=i;}*++s?f(s,d):(d[i]=0);}

致电:

int main()
{
    char *in="Loading... Forever";
    char out[128];
    f(in,out);
    puts(out);
}

1

SAS,108

由于SAS冗长的语法,此处的竞争性较差的答案之一-每个正则表达式9个字符的罚款确实很痛苦-但这是一个很好的正则表达式学习练习:

t=prxchange('s/^-|-$//',-1,prxchange('s/-+/-/',-1,compress(translate(lowcase(t),'----',' .,/'),'-','adk')));

1

Pyth,35个字节

:r::rQ0"[-.,/]"d"[^\w ]"k6"[ -]+"\-

说明

    rQ0                              Convert letters to lower case
   :   "[-.,/]"d                     Replace all -.,/ with spaces
  :             "[^\w ]"k            Remove all remaining symbols
 r                       6           Remove leading and trailing spaces
:                         "[ -]+"\-  Turn runs of spaces and dashes to one dash

1

Perl 6,75

{lc .subst(/<[\ .,/]>/,"-"):g.subst(/<[\W]-[\-]>/,""):g.subst(/\-+/,"-"):g}

0

GNU Sed,65个字节

s/.*/\L\0/
s@[ .,/]@-@g
s/[^-a-z0-9]//g
s/-\+/-/g
s/^-\|-$//g

一系列正则表达式替换。\L从GNU sed 使用不可移植来小写输入。使用从文件运行sed -f

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.