CSS, 132 116 115 bytes
a:not(:last-child):nth-child(n+2):after,a:nth-last-child(n+3):after{content:","}a+:last-child:before{content:"and "
<p>
<a>one</a>
</p>
<p>
<a>one</a>
<a>two</a>
</p>
<p>
<a>one</a>
<a>two</a>
<a>three</a>
</p>
<p>
<a>one</a>
<a>two</a>
<a>three</a>
<a>four</a>
</p>
a:not(:last-child):nth-child(n+2):after,a:nth-last-child(n+3):after{content:","}a+:last-child:before{content:"and "
CSS no se ve con demasiada frecuencia en el código de golf porque solo puede formatear texto, pero en realidad funciona para este desafío y pensé que sería divertido hacerlo. Véalo en acción usando el fragmento de arriba (haga clic en "Mostrar fragmento de código").
La lista debe estar en un archivo HTML vinculado con cada elemento rodeado de <a>
etiquetas y separados por saltos de línea. Los elementos de la lista deben ser los únicos elementos en su elemento principal, por ejemplo
<a>one</a>
<a>two</a>
<a>three</a>
Explicación
a:not(:last-child):nth-child(n+2)::after,
a:nth-last-child(n+3)::after {
content: ",";
}
a + :last-child::before {
content: "and ";
}
Consideremos la versión anterior sin golf. Si no está familiarizado con el funcionamiento de CSS, todo lo que esté fuera de las llaves es un selector que determina el conjunto de elementos HTML a los que se aplican las declaraciones dentro de las llaves. Cada par selector-declaración se llama regla . (Es más complicado que eso, pero será suficiente para esta explicación). Antes de aplicar cualquier estilo, la lista aparece separada solo por espacios.
Queremos agregar comas después de cada palabra, excepto la última, excepto las listas de dos palabras, que no tienen comas. El primer selector, a:not(:last-child):nth-child(n+2):after
selecciona todos los elementos excepto el primero y el último. :nth-child(n+2)
es una forma más corta de decir :not(:first-child)
, y básicamente funciona seleccionando elementos cuyo índice (comenzando en 1) es mayor o igual a 2. (Sí, todavía me confunde un poco. Los documentos MDN podrían ayudar).
Ahora solo tenemos que seleccionar el primer elemento para obtener una coma si hay tres o más elementos en total. a:nth-last-child(n+3):after
funciona como :nth-child
, pero contando desde atrás, por lo que selecciona todos los elementos excepto los dos últimos. La coma toma la unión de los dos conjuntos, y usamos el :after
pseudo-elemento para agregar content
inmediatamente después de cada elemento seleccionado.
La segunda regla es más fácil. Necesitamos agregar "y" antes del último elemento en la lista, a menos que sea un solo elemento. En otras palabras, necesitamos seleccionar el último elemento precedido por otro elemento. +
es el selector de hermanos adyacentes en CSS.