リストからオックスフォードコンマを使用して単一の文字列を生成する


24

文字列のリストを取得し、リストから構築された単一の適切に句読点付きの文字列を返し、各要素を引用する、いくつかの巧妙な(簡潔で慣用的な)アプローチは何ですか?

一方、これは私のために来たのGroovyを試して、私あまりにもリテラルが、説明の解決策があるため、

def temp = things.collect({"\'${it}\'"})
switch (things.size()) {
    case 1:
        result = temp[0]
        break
    case 2:
        result = temp.join(" and ")
        break
    default:
        result = temp.take(temp.size()-1).join(", ") + ", and " + temp[-1]
        break
}

すなわち、['1']得られるはず'1'['1','2']得られるはず'1 and 2'、と[私は?そこに何をしたか見る] ['1','2','3']得なければなりません'1, 2, and 3'

Groovyには良い答えがありますが、他の言語で何ができるかを知りたいです。

これらの言語の機能とイディオムを利用するさまざまな言語のコンパクトな巧妙なアプローチは何ですか?


6
PPCGへようこそ。ここに投稿された一般的な質問は、コミュニティにとっての挑戦です。そのため、客観的な勝利基準が必要です。この質問は、コードゴルフの挑戦であることと合理的にうまく対応していると思います。そのようにタグ付けできますか?もしそうなら、入力と出力の仕様を少し強化する必要があると思います。
デジタル外傷14

7
これは、と、より興味深いものになるだろう本当の文章['we invited the stripper','JFK','Stalin']
ThisSuitIsBlackNot

1
文字列自体に既にコンマが含まれていないと仮定できますか?
マーティンエンダー14

2
チャレンジは、「誰が---- オックスフォードコンマについて語るのか?」
イグビーラージマン

3
@OldCurmudgeon私はあなたが「アメリカのゴミ」を意味すると思う;)
ThisSuitIsBlackNot 14

回答:


76

CSS、132 116 115バイト

a:not(:last-child):nth-child(n+2):after,a:nth-last-child(n+3):after{content:","}a+:last-child:before{content:"and "

CSSはテキストのみの書式設定が可能なため、コードゴルフではあまり見られませんが、実際にはこの課題に対して機能し、楽しいと思いました。上記のスニペットを使用して実際に動作を確認してください(「コードスニペットを表示」をクリックします)。

リストはリンクされたHTMLファイル内にあり、各要素は<a>タグで囲まれ、改行で区切られている必要があります。リスト項目は、親要素内の唯一の要素でなければなりません。例えば

<a>one</a>
<a>two</a>
<a>three</a>

説明

a:not(:last-child):nth-child(n+2)::after,
a:nth-last-child(n+3)::after {
    content: ",";
}

a + :last-child::before {
    content: "and ";
}

上記の非ゴルフバージョンを考えてみましょう。CSSの仕組みに慣れていない場合、中括弧の外側はすべて、中括弧内の宣言が適用されるHTML要素のセットを決定するセレクターです。各セレクター宣言のペアは、ルールと呼ばれます。(それよりも複雑ですが、この説明では十分です。)スタイリングが適用される前に、リストはスペースのみで区切られて表示されます。

最後の単語を除くすべての単語の後にカンマを追加します。ただし、2単語のリストはコンマを取得しません。最初のセレクターはa:not(:last-child):nth-child(n+2):after、最初と最後を除くすべての要素を選択します。:nth-child(n+2)はの簡単な言い方:not(:first-child)であり、基本的には、インデックス(1から始まる)が2以上の要素を選択することで機能します(はい、まだ少し混乱します。MDNのドキュメントが役立つかもしれません)。

合計3つ以上の要素がある場合は、最初の要素を選択してコンマを取得するだけです。a:nth-last-child(n+3):afterはのよう:nth-childに機能しますが、後ろから数えて、最後の2つを除くすべての要素を選択します。コンマは2つのセットの和集合を取り、:after 擬似要素を使用して、content選択した各要素の直後に追加します。

2番目のルールの方が簡単です。単一の要素でない限り、リストの最後の要素の前に「and」を追加する必要があります。つまり、別の要素が先行する最後の要素を選択する必要があります。+ある隣接兄弟セレクタ CSSでは


1
ブリリアント!大好きです。:D
COTO

を使用する場合のみ<li>
スリーブマン14

1
<li>理想的ですが、セレクタに2つの余分な文字が追加されます。私が選んだの<a>は、1文字であり、独自の書式設定を適用しないためです。
NinjaBearMonkey 14

うわー、これは非常に印象的です。賢い賞。

CSSが一番の答えですか?いいね
ブランドン14

13

ハスケル:81、77の 74文字

f[x]=x
f[x,y]=x++" and "++y
f[x,y,z]=x++", "++f[y++",",z]
f(x:y)=x++", "++f y

Haskellの機能:パターンマッチング


いくつかのスペースを削除できます
Ray

1
削除することができますf[x,y,z]
seequ 14

そして今、それはほとんど標準的な再帰です。:)
seequ 14

あなたはオックスフォードのコンマとコンマの後のスペースを忘れていました- f["a","b","c"]あるはずですが"a, b, and c"、それは"a,b and c"
誇りに思っていますhaskeller 14

4
:)に置き換えることy++", and "++zによってゴルフはどうf[y++",",z]
ですか

7

ルビー、47バイト

q=" and ";p$*[2]?(a=$*.pop;$**", "+?,+q+a):$**q

説明

  • 入力はコマンドライン引数($*)です。
  • $*3番目の要素がある場合($*[2]nilを返さない)、最後の要素を除くすべての要素を取得し、を使用してコンマ区切りの文字列に変換しますArray#*。最後に、余分なコンマ、文字列" and "、最後のコマンドライン引数を追加します。
  • $*3番目の要素がない場合、2、1、または0個の引数が指定されました。引数を安全に文字列" and "と結合して、正しい結果を生成できます。

6

Python 2(61)

s=input()
d=s.pop()
print", ".join(s)+", and "[8-7*len(s):]+d

主なトリックは", and "、1つと2つの要素の最終的なジョイナーの一部を切り捨てることです。1つはすべてが切り取られ、2つはコンマが削除されます。これは、スライスすることによって行われます[8-7*len(s):](これはのs後に1つ短くなることに注意してくださいpop)。

残念ながら、d単にその表現で置き換えることはできませんpop


間違っていなければ、最初の行sを置き換えてs=input()、最初の行を削除できます。2文字節約します。
tomsmeding

@tomsmedingあなたが何を提案しているのか分かりません。コードはs複数回参照しています。
xnor 14

待って、今朝は変なことをする。やっぱりなんでもないや。:)
14

6

CSS、 62文字 112文字

他のエントリーからインスピレーションを得て、さらに短くなりました。A要素が空白で区切られていないことが必要であることに注意してください。

a+a:before{content:", "}a+a:last-child:before{content:", and "

http://jsfiddle.net/olvlvl/1Ls79ocb/

デニスが指摘したように、「1と2」を修正します。

a+a:before{content:", "}a+a:last-child:before{content:", and "}a:first-child+a:last-child:before{content:" and "

http://jsfiddle.net/olvlvl/1Ls79ocb/3/


5

Perl(v 5.10以降)-37 35 34 28

@F>2&&s/ /, /g;s/.* \K/and /

で実行するperl -apeために、リストで指定されたスペースで区切られSTDINます

さまざまな入力の出力:

$ perl -ape '@F>2&&s/ /, /g;s/.* \K/and /'
oxford
oxford
oxford cambridge
oxford and cambridge
oxford cambridge comma
oxford, cambridge, and comma
oxford cambridge comma space
oxford, cambridge, comma, and space

あなたはにあなたの最後の置換を変更することにより、3バイトで、これを減らすことができますs/(\S+)$/and $1/
ThisSuitIsBlackNot

1
@ThisSuitIsBlackNot '\ n'(ありがとう)はドロップできますが、スペースはドロップできません。または、「x」の入力が「and x」になります
14

おっと、より多くの入力でテストする必要がありました。とにかく、$編集でアンカーを忘れたので、の入力はにfoo bar bazなりfoo, and bar, bazます。また、あなたは削除することができます1実行して、スペースのs/( \S+)$/ and$1/
ThisSuitIsBlackNot

私の最後のコメントはまだ35であなたを残していますが、書くことができる$#F>1よう@F>21以上剃り落とすへ。マイクロ改善のためのすべての提案を申し訳ありませんが、私はこの答えが本当に好きです:)
ThisSuitIsBlackNot

@ThisSuitIsBlackNotではありません-マイクロエディットを歓迎します。私は密かに28バイトのCJamと30バイトのGolfscriptと競合しています。しかし、私は最後にコメントの翻訳を行わずに34に到達しました(でテストしました。33文字になるecho -n ... | wc -c)前にスペースを逃し(\S+)た場合、入れたtest this場合はtest and this(後に2スペースtest)になりますので、それは間違っていると思います。
14

4

Javascript(63)

l=a.length;l>2&&(a[l-1]='and '+a[l-1]);a.join(l>2?', ':' and ')

事例:

  • a = [1] => 1
  • a = [1, 2] => 1 and 2
  • a = [1, 2, 3] => 1, 2, and 3

警告:これは、長さが2を超える配列の最後の要素を変更します。


2
良い使用&&
クリスブルーム14

4

GNU sed- -rフラグ用の1を含む69文字

s/ /, /g
s/( [^ ]+)( [^ ]+)$/\1 and\2/
s/^([^,]+),([^,]+)$/\1 and\2/

スペースで区切られたリストを使用します(シェルスクリプトではかなり慣用的です)。

$ sed -r -f oxfordcomma.sed <<< "1"
1
$ sed -r -f oxfordcomma.sed <<< "1 2"
1 and 2
$ sed -r -f oxfordcomma.sed <<< "1 2 3"
1, 2, and 3
$

はい、code-golfに行きましょう。
オロム14

2番目の出力は1 and 21, 2
Optimizer 14

@Optimizer-まったくその通り。一定。
デジタル外傷14

3

Python 2- 71 70 68

s=input()
l=len(s)-1
print', '.join(s[:l])+', and '[l<2:]*(l>0)+s[l]

inputおよびの両方を含む文字数print


3

ルビー、57バイト

f=->l{s=l*', ';s.sub(/,(?!.*,)/,(l.size<3?'':?,)+' and')}

文字列を結合し、文字列,の最後のコンマをand(およびリストの長さに応じてオプションのコンマ)に置き換えます。


3

コブラ-60

do(l as String[])=l.join(', ',if(l.length<3,'',',')+' and ')

CobraのList<of T>.join関数を使用すると、リストの最後の2つの要素に異なるセパレーターを指定できます。これにより、これが非常に短くなります。


3

Perl-59

sub f{$a=join', ',@_;$#_&&substr$a,(@_>2)-3,@_<3,' and';$a}

リストをコンマで結合し、リストに複数の要素がある場合' and'、最後のコンマの後に追加するか(長さ> = 3の場合)、最後のコンマをそれに置き換えます(長さ== 2の場合)。


3

PHP、192の 167 146 136文字:

$n=' and ';$s=count($a);echo ($s<3)?join($n,$a):join(', ',array_merge(array_slice($a,0,$s-2),Array(join(",$n",array_slice($a,-2,2)))));

私が数年前にhttp://www.christopherbloom.com/2011/05/21/join-implode-an-array-of-string-values-with-formatting/で書いた関数に基づいて


コードを(オックスフォードコンマで)回答テキストに入れていただけますか?

うん、ごめん。私は自分の電話にいて、コードを適切に貼り付けませんでした。デスクトップから更新します
クリスブルーム14

@ Chrisbloom7を追加するのは簡単であっても、答えには、1つにできるコードではなく、作業コードを含める必要があります。また、目的はコードをできるだけ小さくすることであるため、機能するコードを投稿しないとスコアが存在しなくなります。
誇りに思ってhaskeller 14

再度おologiesび申し上げます。CGでの初めてのポスター。私は答えを修正しました
クリスブルーム14

3

バッチ-151バイト

@echo off&set f=for %%a in (%~1)do
%f% set/aa+=1
%f% set/ac+=1&if !c!==1 (set o=%%a)else if !c!==!a! (set o=!o!, and %%a)else set o=!o!, %%a
echo !o!

注意; スイッチをに設定cmdしてからスクリプトを呼び出す必要があるため、スクリプトに長いコードを含める必要はありません。それ以外の場合は、バイトカウントに30を追加し、通常どおりスクリプトを呼び出します。/vonsetLocal enableDelayedExpansion

h:\uprof>cmd /von /c test.bat "1 2 3"
1, 2, and 3

h:\uprof>cmd /von /c test.bat "1 2 3 4 5"
1, 2, 3, 4, and 5

3

Groovy、47 43 57文字、JavaScript ES6 56文字

グルーヴィー:

(a[1]?a[0..-2].join(", ")+(a[2]?",":"")+" and ":"")+a[-1]

配列は文字で埋められているため、次のように置き換えることができます a.size>1によってa[1]

JavaScript、ES6:

a.join(', ').replace(/,([^,]+)$/,`${a[2]?',':''} and$1`)

どちらの場合も、変数aに問題の配列があると想定しています。


6
オックスフォードコンマ、接続詞の前のコンマです
デニス14

3

PHP、86 84文字

$a = ['one', 'two', 'three', 'four', 'five'];

配列が初期化されたら、カウントを開始します。

$L=count($a)-1;$S=', ';$L<2?($S=' and '):($a[$L]='and '.$a[$L]);echo implode($S,$a);

プリティファイド:

$last_index = count($a) - 1;
$separator = ', ';
if ($last_index < 2) {
    $separator = ' and ';
} else {
    $a[$last_index] = 'and '.$a[$last_index];
}
echo implode($separator, $a);

リストの最後のアイテムが変更されます。PHPでは配列の割り当てと関数呼び出しがコピーを実行するため、これは問題ないはずです。


3

CJam、35 30 28 27バイト

q~)\_"and "L?@+a+_,2=", ">*

これは、STDINから読み取り、STDOUTに出力するプログラムです。 オンラインでお試しください。

使い方

q~                                     " Q := eval(input())                               ";
  )                                    " P := Q.pop()                                     ";
   \_"and "L?@+                        " P := (Q ? 'and ' : '') + P                       ";
                a+                     " Q += [P]                                         ";
                  _,2=", ">            " J := ', '[(len(Q) == 2):]                        ";
                           *           " R := J.join(Q)                                   ";
                                       " print R (implicit)                               ";

実行例

$ cjam <(echo 'q~)\_"and "L?@+a+_,2=", ">*') <<< '["1"]'; echo
1
$ cjam <(echo 'q~)\_"and "L?@+a+_,2=", ">*') <<< '["1""2"]'; echo
1 and 2
$ cjam <(echo 'q~)\_"and "L?@+a+_,2=", ">*') <<< '["1""2""3"]'; echo
1, 2, and 3
$ cjam <(echo 'q~)\_"and "L?@+a+_,2=", ">*') <<< '["1""2""3""4"]'; echo
1, 2, 3, and 4

私はあなたの尻尾にいます-以下を参照してください:
14

3

Googleスプレッドシート、67 68 67 92バイト

=SUBSTITUTE(JOIN(", ",FILTER(A:A,A:A<>"")),",",IF(COUNTA(A:A)>2,",","")&" and",COUNTA(A:A)-1

入力はセルから始まり、A1多くのエントリが存在する場合は下に向かって続きます。
JOINそれらをすべて、それぞれの間にカンマスペースを使用して文字列にマージします。
FILTER空白以外を削除するため、末尾に無限のコンマが表示されなくなります。
SUBSTITUTE最後のコンマを置き換えます(COUNTA非空白の入力をカウントすることで見つかります)。

それほどエキサイティングではありませんが、単一のセルで実行できます。


これにより、オックスフォードコンマが除外されます。

@Umbrellaまあ、それは私の愚かさでしたね?+1バイト
エンジニアトースト

)-1バイトの場合、この式から端末をドロップできるはずです。まあ、それは私が今まで見た中で最も早い編集だった+1
テイラースコット

これをテストした後2つのノートは- A:A>""に変換する必要がありA:A<>""、これが唯一の2つのオブジェクトの例にオックスフォードのカンマを省略実装していない
テイラー・スコット

@TaylorScott私は今までテキストでテストしただけで、問題を逃したと思います>""。以前に明らかにした急ごしらえの修正は、テストされていません。私は方向好きではない...行ってきました
エンジニアトースト

2

JavaScript(ES6)60

入力配列に空の文字列がないと仮定

f=(a,b=a.pop())=>a[0]?a.join(', ')+(a[1]?',':'')+' and '+b:b

FireFox / Firebugコンソールでテストする

console.log(f(['We invited the stripper','JFK','Stalin']))

出力

 We invited the stripper, JFK, and Stalin

これを実行するにはどうすればよいですか?私node --harmonyは文字列の配列でそれを試しましたvar a = 'abcdefgh'.split('');が、それはただそこにあり、...何もしないようです。また、独自のES6機能を使用するための+1 ()=>
エイドリアン14

@Adrianは、出力なしで文字列を返します。答えにテストを追加します。
edc65 14

f=(a,b=a.pop())=>a[0]?a.join(', ')+', and '+b:bも正しいと思うし、13バイト短くなっています。
インゴ・バーク

1
@IngoBürkは、2つの項目を持つコンマを処理する部分を切り取ります。何だと思う?2つのアイテムでは、出力が間違っています。
edc65

@ edc65ああ、どー。悪いかもしれません。
インゴバーク14

2

JavaScript- 60 56 71 67 63

まったく慣用的なアプローチではありませんが、私はそれを書くのが楽しく、正規表現が好きです。

配列が次の場所に保存されていると仮定しvar aます。

a.join((a.length>2?',':'')+' ').replace(/([^,\s])$/,"and $1")

単純にインデックスをチェックすることで短縮されます[2]:(yay boolean coercion)

a.join((!!a[2]?',':'')+' ').replace(/([^,\s])$/,'and $1')

どうやら私はテストを嫌い、単一エントリのテストをスキップしました。修正版は次のとおりです。

a.join((!!a[2]?',':'')+' ').replace(/([^,\s])$/,(!!a[1]?'and ':'')+'$1')

ブール値を反転して2文字を削除し、スペースを連結から最初の3進数のthen / elseに移動してさらに3文字削除しました。

a.join((!a[2]?' ':', ')).replace(/([^,\s])$/,(!a[1]?'':'and ')+'$1')

JSが私に代わってブール値を強制する必要がないことを思い出させてくれた@tomsmedingに感謝します。また、次の内部の連結から最初の3項を分離する括弧を削除するのを忘れたことに気付きましたjoin()

a.join(a[2]?', ':' ').replace(/([^,\s])$/,(a[1]?'and ':'')+'$1')

私はそうしましたか?義務的な新しいゴルファーの謝罪。


1
正規表現の好みは、マゾヒズムとして知られています。
seequ 14

実際には、まったく必要ありませんでした!!a[2]?A:Bすでに動作します。ブール値を再度反転する必要がある場合があります。
tomsmeding

@tomsmeding-あなたは正しいです。私は手動で私のブール値を強制することの習慣の中で生まれ、持っているので、私は...、いつものJavaScriptのデフォルトのboolean型の強制行動を警戒しています
エイドリアン

@Adrian Correction:空の文字列以外の値の場合、truea[i]同等です。よくほとんど。入力が2つある場合、配列の長さは2であると想定しています。次にa[2]===undefined、とundefined評価しfalseます。編集:あなたの編集は私が意図したものです:)
tomsmeding

2

Golfscript- 31 39 34 30

こんにちは世界!私は長い間潜んでいる、初めてのポスターです。Golfscriptの30バイトのソリューションを次に示します([1 2 3]などの配列が既にスタックにある場合)。

.,3<" and ":A{~A(;\+]", "}if*

結果はすべてのテストケースに適切です。

編集:CJam、それを取ります!


長さ1の配列を考慮して編集されました。
ジョサイアWinslow

より効率的なアルゴリズムのために編集されました。
ジョサイアウィンズロー14

戦いは続きます。:P
デニス14

ああ、でも今はそうです。:P
ジョサイアウィンズロー14

2

Xojo、52 71 83文字

dim i as int8=ubound(L)
L(i)=if(i=0,"","and ")+L(i)
Return L.Join(if(i=1," ",", ")

UBoundは配列の長さより1つ小さいことに注意してください。


いけない-これは、2つの項目がある場合、カンマを追加しているようだ
edc65

良いキャッチ。修正するために編集されました。
シルバーパイ14

2

Excel VBA、108バイト

入力を範囲からスペースで区切られた配列として受け取りA1、VBEイミディエイトウィンドウに出力する匿名VBEイミディエイトウィンドウ関数。

x=Split([A1]):y=UBound(x):For i=0To y-2:?x(i)", ";:Next:If y>0Then?x(i)IIf(y>1,",","")" and "x(i+1)Else?[A1]


1

Python 62文字

iが文字列のリストであると仮定すると:

(" and", ", and")[len(i) < 2].join(", ".join(i).rsplit(",",1))


1

ジュリア(53)

print(join(ARGS,", ",(endof(ARGS)>2?",":"")" and "))

STDINから引数を取り、STDOUTに出力します

Base.join(items、delim [、last])を使用したソリューション

編集:

テストケース

julia oxfordComma.jl 1

1

julia oxfordComma.jl 1 2

1と2

julia oxfordComma.jl 1 2 3

1、2、および3


1
ジュリアはわかりませんが、オックスフォードコンマが生成されないようです。
flornquake 14

@flornquakeそれが原因オプションの「最後」の引数に、オックスフォードコンマで印刷を行います
Cruor

2
そう1, 2, and 3ではないはず1, 2 and 3です。
flornquake 14

1

暴言(108)

[$[l:@b]:[r:each][s:[cmp:[rc];2;[is:different;,]]\s][before:[last:[notfirst:and\s]]][sync:;ordered][arg:b]]

ゴルフをしていない:

[$[l:@b]:
    [r:each]                            # Repeat for each item
    [s:[cmp:[rc];2;[is:different;,]]\s] # Separate by comma if n > 2
    [before:[last:[notfirst:and\s]]]    # Insert "and" before last item
    [sync:;ordered]                     # Force forward order
    [arg:b]                             # Read list
]

使用法:

[$l:{A|B|C|D|E}]

オンラインで試す


1

Pyth、28

j>", "qlQ2+_t_Q+?"and "tQkeQ

例:

$ pyth programs/oxford.pyth <<< "['1']"
1

$ pyth programs/oxford.pyth <<< "['1','2']"
1 and 2

$ pyth programs/oxford.pyth <<< "['1','2','3']"
1, 2, and 3

入力のフォーマット方法がわからないようです。
デニス14年

@Dennisいくつかのテストケースを追加します。
isaacg 14年

実際に試してみましたが、私のバージョンのPyth(TypeError: can only concatenate list (not "str") to list)では動作しませんでした。最新バージョンでも問題なく動作します。
デニス14年

@Dennis Yeah、リストへの追加ルールはごく最近追加されました。
isaacg 14年

1

PHP-72

入力を設定します。

$i=[1,2,3,4,5];

そして、プロセス:

$x=count($i)-1;if($x) {$i[$x]=" and ".$i[$x];}echo join($x>1?",":"",$i);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.