การสร้างสตริงเดียวด้วยคอมม่า Oxford จากรายการ


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 โดยทั่วไปคำถามที่โพสต์ที่นี่เป็นสิ่งที่ท้าทายต่อชุมชน เช่นนี้พวกเขาต้องการเกณฑ์การชนะอย่างมีวัตถุประสงค์ ฉันเชื่อว่าคำถามนี้แผนที่ดีพอสมควรกับความท้าทายรหัส - กอล์ฟ คุณสามารถแท็กมันได้หรือไม่ ถ้าเป็นเช่นนั้นฉันคิดว่าคุณควรกระชับข้อกำหนดอินพุตและเอาต์พุตเล็กน้อย
Digital Trauma

7
สิ่งนี้น่าสนใจยิ่งขึ้นกับประโยคจริง :['we invited the stripper','JFK','Stalin']
ThisSuitIsBlackNot

1
เราสามารถสันนิษฐานได้ว่าตัวสตริงเองไม่มีเครื่องหมายจุลภาคอยู่แล้ว?
Martin Ender

2
ความท้าทายควรมีชื่อว่า "ใครให้คำตอบ ---- กับเครื่องหมายจุลภาคของฟอร์ด "
Igby Largeman

3
@ OldCurmudgeon ฉันคิดว่าคุณหมายถึง "ขยะ Americanized";)
ThisSuitIsBlackNot

คำตอบ:


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 ไม่เห็นบ่อยเกินไปใน code golf เพราะมันสามารถจัดรูปแบบข้อความเท่านั้น แต่ใช้งานได้กับความท้าทายนี้และฉันคิดว่ามันสนุกที่จะทำ ดูการทำงานโดยใช้ข้อมูลโค้ดด้านบน (คลิก "แสดงข้อมูลโค้ด")

รายการควรอยู่ในไฟล์ 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 ที่มีการประกาศภายในวงเล็บปีกกา แต่ละคู่เลือกประกาศจะเรียกว่าเป็นกฎ (มันซับซ้อนกว่านั้น แต่พอเพียงสำหรับคำอธิบายนี้) ก่อนที่จะใช้สไตล์ใด ๆ รายการจะปรากฏโดยคั่นด้วยช่องว่างเท่านั้น

เราต้องการเพิ่มเครื่องหมายจุลภาคหลังทุกคำยกเว้นที่ผ่านมายกเว้นสำหรับรายการที่มีสองคำซึ่งไม่ได้รับเครื่องหมายจุลภาค ตัวเลือกแรกa:not(:last-child):nth-child(n+2):afterเลือกองค์ประกอบทั้งหมดยกเว้นตัวแรกและตัวสุดท้าย :nth-child(n+2)เป็นวิธีที่สั้นกว่าในการพูด:not(:first-child)และใช้งานได้โดยการเลือกองค์ประกอบที่ดัชนี (เริ่มต้นที่ 1) มากกว่าหรือเท่ากับ 2 (ใช่มันยังทำให้ฉันสับสนเล็กน้อยเอกสาร MDNอาจช่วยได้)

ตอนนี้เราแค่ต้องเลือกองค์ประกอบแรกเพื่อรับเครื่องหมายจุลภาคถ้ามีองค์ประกอบสามอย่างหรือมากกว่านั้น a:nth-last-child(n+3):afterทำงานเหมือน:nth-childแต่นับจากด้านหลังดังนั้นจึงเลือกองค์ประกอบทั้งหมดยกเว้นสองรายการสุดท้าย เครื่องหมายจุลภาคใช้การรวมกันของสองชุดและเราใช้:after องค์ประกอบหลอกเพื่อเพิ่มcontentทันทีหลังจากแต่ละองค์ประกอบที่เลือก

กฎข้อที่สองง่ายกว่า เราจำเป็นต้องเพิ่ม "และ" ก่อนองค์ประกอบสุดท้ายในรายการยกเว้นว่าจะเป็นองค์ประกอบเดียว กล่าวอีกนัยหนึ่งเราต้องเลือกองค์ประกอบสุดท้ายที่นำหน้าด้วยองค์ประกอบอื่น +เป็นตัวเลือกพี่น้องที่อยู่ติดกันใน CSS


1
ยอดเยี่ยม! ฉันรักมัน. : D
COTO

<li>เพียงแค่คุณต้องการใช้
slebetman

1
<li>จะเป็นอุดมคติ แต่นั่นจะเพิ่มอักขระพิเศษสองตัวลงในตัวเลือก ฉันเลือก<a>เพราะเป็นตัวอักษรเดียวและไม่ได้ใช้การจัดรูปแบบของตัวเอง
NinjaBearMonkey

ว้าว ... มันน่าประทับใจมาก รางวัลความฉลาด

CSS เป็นคำตอบที่ดีที่สุด? ดี
Brandon

13

Haskell: 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

และตอนนี้มันเป็นการเรียกซ้ำมาตรฐานค่อนข้างมาก :)
seequ

คุณลืมเครื่องหมายจุลภาคออกฟอร์ดและช่องว่างหลังจากเครื่องหมายจุลภาค - f["a","b","c"]ควรเป็น"a, b, and c"แต่เป็น"a,b and c"
ภาคภูมิใจ Haskeller

4
วิธีการเกี่ยวกับการเล่นกอล์ฟโดยการแทนที่y++", and "++zโดยf[y++",",z]:)
haskeller ความภาคภูมิใจที่

7

Ruby, 47 ไบต์

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

คำอธิบาย

  • อินพุตเป็นอาร์กิวเมนต์บรรทัดคำสั่ง ( $*)
  • เมื่อ$*มีองค์ประกอบที่สาม ( $*[2]ไม่กลับไม่มี) ใช้องค์ประกอบทั้งหมดลบหนึ่งที่ผ่านมาและเปิดให้เป็นที่คั่นด้วยจุลภาค String Array#*ใช้ ในที่สุดเพิ่มเครื่องหมายจุลภาคพิเศษสตริง" and "และอาร์กิวเมนต์บรรทัดคำสั่งสุดท้าย
  • เมื่อ$*ไม่มีอิลิเมนต์ที่สามจะมีการกำหนดอาร์กิวเมนต์สองหนึ่งหรือหนึ่งรายการ ข้อโต้แย้งสามารถเข้าร่วมกับสตริงได้อย่างปลอดภัย" and "และให้ผลลัพธ์ที่ถูกต้อง

6

Python 2 (61)

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

เคล็ดลับหลักคือการตัดส่วนของผู้เข้าร่วมสุดท้าย", and "สำหรับองค์ประกอบหนึ่งและสอง สำหรับหนึ่งทั้งหมดมันถูกตัดออกและสองเครื่องหมายจุลภาคจะถูกลบออก ทำได้โดยการแบ่งส่วนออก[8-7*len(s):](สังเกตว่าsสั้นกว่าหนึ่งpop)

น่าเสียดายที่dไม่สามารถถูกแทนที่ด้วยการแสดงออกของมันหรือสิ่งที่popจะเกิดขึ้นสายเกินไป


คุณสามารถแทนที่บรรทัดแรกsด้วยs=input()และลบบรรทัดแรกถ้าฉันไม่ผิด บันทึก 2 ตัวอักษร
tomsmeding

@tomsmeding ฉันไม่เข้าใจสิ่งที่คุณกำลังแนะนำ รหัสนี้อ้างถึงsหลายครั้ง
xnor

เมื่อเช้านี้ฉันทำสิ่งแปลก ๆ ลืมมันซะ. :)
tomsmeding

6

CSS, 62 ตัวอักษร 112 ตัวอักษร

แรงบันดาลใจจากรายการอื่น ๆ แม้สั้น โปรดทราบว่ามันต้องการให้องค์ประกอบ A ไม่ได้ถูกคั่นด้วยช่องว่างสีขาว:

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

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

แก้ไขสำหรับ "หนึ่งและสอง" ตามที่เดนนิสชี้:

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 -apeSTDIN

เอาต์พุตสำหรับอินพุตต่างๆ:

$ 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" กลายเป็น "และ x"
abligh

โอ๊ะควรทดสอบด้วยอินพุตเพิ่มเติม อย่างไรก็ตามคุณลืม$สมอในการแก้ไขของคุณเพื่อให้การป้อนข้อมูลของจะกลายเป็นfoo bar baz foo, and bar, bazนอกจากนี้คุณสามารถลบหนึ่งในช่องว่างโดยทำs/( \S+)$/ and$1/
ThisSuitIsBlackNot

ความคิดเห็นล่าสุดของฉันยังคงใบคุณที่ 35 แต่คุณสามารถเขียน$#F>1เป็น@F>2ไปโกนออกอีกครั้งหนึ่ง ขออภัยสำหรับคำแนะนำทั้งหมดสำหรับการปรับปรุงเล็ก ๆ ฉันชอบคำตอบนี้จริงๆ :)
ThisSuitIsBlackNot

@ ThisSuitIsBlack ไม่เป็นไร - ยินดีต้อนรับ microedits ฉันแอบแข่งขันกับ CJam 28 ไบต์และ Golfscript 30 ไบต์ อย่างไรก็ตามฉันได้รับถึง 34 โดยไม่ต้องทำการแปลความคิดเห็นของคุณก่อนที่ผ่านมา (ทดสอบด้วยecho -n ... | wc -c)หากคุณพลาดช่องว่างก่อนที่(\S+)คุณจะได้รับถึง 33 ตัวอักษร แต่ถ้าคุณใส่ในtest thisคุณจะได้รับtest and this(ช่องว่างสองหลังtest) ดังนั้นโดยไม่ต้องเพิ่มเติม ฉันคิดว่าผิด
abligh

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

Caveat: สิ่งนี้จะแก้ไของค์ประกอบสุดท้ายในอาร์เรย์ที่มีความยาว> 2


2
ใช้งานได้ดี&&
Chris Bloom

4

GNU sed - 69 chars รวม 1 สำหรับ-rflag

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
$

ใช่ให้เป็นไปด้วยรหัสกอล์ฟ
orome

เอาท์พุทที่สองควรจะ1 and 2แทน1, 2
เพิ่มประสิทธิภาพ

@Optimizer - ค่อนข้างถูกต้อง คงที่
Digital Trauma

3

Python 2 - 71, 70 68

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

นับจำนวนตัวอักษรรวมทั้งสองและinputprint


3

Ruby, 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 ')

List<of T>.joinฟังก์ชั่นของคอบร้าช่วยให้คุณระบุตัวคั่นที่แตกต่างกันสำหรับสององค์ประกอบสุดท้ายของรายการซึ่งเป็นสิ่งที่ทำให้สิ่งนี้สั้นมาก


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/


คุณกรุณาใส่รหัสของคุณ (ด้วยคอมม่า Oxford) ลงในข้อความคำตอบได้หรือไม่?

ใช่ขอโทษ. ฉันอยู่ในโทรศัพท์ของฉันและจะไม่วางรหัสอย่างถูกต้อง ฉันจะอัปเดตจากเดสก์ท็อปของฉัน
Chris Bloom

@ Chrisbloom7 แม้ว่าจะเพิ่มเล็กน้อยคำตอบควรมีรหัสที่ใช้งานได้ไม่ใช่รหัสที่สามารถทำให้เป็นหนึ่งได้ นอกจากนี้เนื่องจากวัตถุประสงค์คือการทำให้รหัสมีขนาดเล็กที่สุดเท่าที่จะทำได้การไม่โพสต์รหัสการทำงานทำให้คะแนนของคุณไม่มีอยู่
ภูมิใจ haskeller

ขอโทษอีกครั้ง โปสเตอร์ครั้งแรกที่ CG ฉันแก้ไขคำตอบของฉันแล้ว
Chris Bloom

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การ/vตั้งค่าสวิตช์onเป็นดังนั้นฉันจึงไม่ต้องรวมความยาวsetLocal enableDelayedExpansionในสคริปต์ มิฉะนั้นเพิ่ม 30 ให้กับจำนวนไบต์และเรียกใช้สคริปต์ตามปกติ

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 ตัวอักษร

Groovy:

(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
คอมม่าออกซ์ฟอร์ดเป็นเครื่องหมายจุลภาคก่อนการรวม
Dennis

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);

prettified:

$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 bytes

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

ฉันอยู่บนหางของคุณ - ดูด้านล่าง :-)
abligh

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นับอินพุตที่ไม่ว่าง)

It's not very exciting but it's doable in a single cell.


This leaves out the oxford comma.
Umbrella

@Umbrella Well, that was stupid of me, wasn't it? +1 bytes
Engineer Toast

You should be able to drop the terminal ) off of this formula for -1 Byte; Well dang, that was the quickest edit I've ever seen +1
Taylor Scott

Two notes after testing this - A:A>"" should be converted to A:A<>"" and this does not implement omitting the oxford comma on cases of only 2 objects
Taylor Scott

@TaylorScott I guess I only ever tested with text and missed the issue with >"". The quickie correction I made earlier clearly wasn't tested. I don't like the direction that went...
Engineer Toast

2

JavaScript (ES6) 60

Assuming no empty strings in input array

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

Test In FireFox/Firebug console

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

Output

 We invited the stripper, JFK, and Stalin

How do I run this? I tried it in node --harmony with an array of strings var a = 'abcdefgh'.split('');, but it just sits there with a ... and appears to do nothing. Also +1 for using unique ES6 feature ()=>.
Adrian

@Adrian the function returns a string, without any output. I'll add a test in the answer.
edc65

I think f=(a,b=a.pop())=>a[0]?a.join(', ')+', and '+b:b is also correct and 13 bytes shorter.
Ingo Bürk

1
@IngoBürk that cuts the part that handles the comma having 2 items. Guess what? With 2 items the output is wrong.
edc65

@edc65 Ah, d'oh. May bad.
Ingo Bürk

2

JavaScript - 60 56 71 67 63

Not exactly an idiomatic approach, but I had fun writing it and I like regex.

Assuming the array is stored in var a:

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

Shortened by simply checking for index [2]: (yay boolean coercion)

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

Apparently I suck at testing and skipped a single-entry test. Here's the fixed version:

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

Shaved off 2 chars by inverting my booleans and 3 more by moving the space from the concatenation into the then/else of the first ternary:

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

Thanks to @tomsmeding for reminding me that I don't have to coerce my booleans because JS does that for me. I also realised I forgot to remove the parentheses separating the first ternary from the concatenation inside the join():

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

Did I do that right? Obligatory new golfer apology.


1
Liking regex is known as masochism.
seequ

Actually you didn't need the !! at all; a[2]?A:B works already. Might have to invert your booleans again.
tomsmeding

@tomsmeding -- you are correct. I am always wary of JavaScript's default boolean coercion behaviour, so I have the borne-in habit of manually coercing my booleans...
Adrian

@Adrian Correction: for any value but an empty string, a[i] equates to true. Well, almost. I'm assuming that if you get 2 inputs, your array has length two. Then a[2]===undefined and undefined evaluates to false. EDIT: your edit is what I meant :)
tomsmeding

2

Golfscript - 31 39 34 30

Hello, World! I am a long time lurker, first time poster. Here is my 30 byte solution in Golfscript (given the array such as [1 2 3] is already on the stack).

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

The results are proper for all test cases.

EDIT: Take that, CJam!


Edited to account for the length 1 array.
Josiah Winslow

Edited for a more efficient algorithm.
Josiah Winslow

The battle continues. :P
Dennis

Ah, but now we're even. :P
Josiah Winslow

2

Xojo, 52 71 83 chars

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

Note that UBound is one less than the array length.


This seems to add the comma when there are 2 items - should not
edc65

Good catch. Edited to fix.
silverpie

2

Excel VBA, 108 Bytes

Anonymous VBE immediate window function that takes input as space delimited array from range A1 and outputs to the VBE immediate window.

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

Julia (53)

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

Takes args from STDIN and outputs to STDOUT

Solution using Base.join(items, delim[, last])

Edit:

Test cases

julia oxfordComma.jl 1

1

julia oxfordComma.jl 1 2

1 and 2

julia oxfordComma.jl 1 2 3

1, 2, and 3


1
I don't know Julia, but this looks like it doesn't generate the Oxford comma.
flornquake

@flornquake it does print with the Oxford comma, due to the optional "last" argument
Cruor

2
It should be 1, 2, and 3, not 1, 2 and 3.
flornquake

1

Rant (108)

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

Ungolfed:

[$[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
]

Usage:

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

Try it online


1

Pyth, 28

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

Examples:

$ 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

I can't seem to figure out how the input should be formatted.
Dennis

@Dennis I'll add some test cases.
isaacg

I had actually tried that, but it didn't work with my version of Pyth (TypeError: can only concatenate list (not "str") to list). It works fine with the latest version.
Dennis

@Dennis Yeah, the adding to list rule was added quite recently.
isaacg

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.