Para una tarea, tengo que escribir una función que imprima el número de números pares cuando se proporciona una secuencia de números.
Usé el código que usé para una tarea anterior (para imprimir 1
cuando un número era par y 0
cuando el número era impar)
Mi problema ahora es que mi función sigue imprimiendo 0
. ¿Qué estoy haciendo mal?
Aquí está mi guión:
#!/usr/bin/bash
# File: nevens.sh
# Write a function called nevens which prints the number of even numbers when provided with a sequence of numbers.
# Check: input nevens 42 6 7 9 33 = output 2
function nevens {
local sum=0
for element in $@
do
let evencheck=$(( $# % 2 ))
if [[ $evencheck -eq 0 ]]
then
let sum=$sum+1
fi
done
echo $sum
}
Respuestas:
Simplemente olvidó reemplazar
$#
con ($
)element
en elfor
bucle:Ahora para probar la función:
fuente
@dessert ha encontrado el problema central, daré una revisión de código:
/usr/bin/bash
en Ubuntu. Es/bin/bash
.Es bueno que hayas declarado
sum
local
y evitado contaminar el espacio de nombres variable fuera de la función. Además, puede declararlo como una variable entera utilizando la-i
opción:¡Siempre cita tus variables (y parámetros)! No es necesario en este script, pero es un muy buen hábito para entrar:
Dicho esto, puedes omitir el
in "$@"
aquí:Cuando
in <something>
no se proporciona, elfor
bucle recorre implícitamente los argumentos. Esto puede evitar errores como olvidar las comillas.No hay necesidad de calcular y luego verificar el resultado. Puedes hacer el cálculo directamente en
if
:(( ... ))
Es el contexto aritmético . Es más útil que[[ ... ]]
para realizar comprobaciones aritméticas, y además puede omitir las$
variables anteriores (lo que hace que sea más fácil de leer, en mi humilde opinión).Si movió la parte de verificación uniforme a una función separada, podría mejorar la legibilidad y la reutilización:
fuente
sum=$((sum + 1 - element % 2))
.&1
verificar el bit bajo si eso es más legible para usted). Pero podemos hacerlo más legible:sum=$((sum + !(element&1) ))
usar un inverso booleano en lugar de+1 - condition
. O simplemente cuente los elementos impares con((odd += element&1))
, y al final imprima conecho $(($# - element))
, porqueeven = total - odd
.local -i
ysum++
.No estoy seguro si estás abierto a otras soluciones. Además, no sé si puede utilizar utilidades externas, o si está limitado exclusivamente a bash builtins. Si puede usar
grep
, por ejemplo, su función podría ser mucho más simple:Esto coloca cada número entero de entrada en su propia línea y luego usa
grep
para contar las líneas que terminan en un dígito par.Actualización: @PeterCordes señaló que incluso podemos hacer esto sin grep, solo bash puro, siempre que la lista de entrada contenga enteros bien formados (sin puntos decimales):
Esto funciona creando una lista llamada
evens
al filtrar todas las probabilidades y luego devolver la longitud de esa lista.fuente
3.0
como un número par; la pregunta no era precisa sobre qué forma tomarían los números.${/%/}
la@
matriz para requerir una coincidencia al final de la cadena, dentro de un inicializador de matriz. Imprime el recuento. Como de una sola línea para definir y ejecutar:foo(){ evens=( ${@/%*[13579]/} ); echo "${#evens[@]} even numbers"; printf "%s\n" "${evens[@]}"; }; foo 135 212 325 3 6 3 4 5 9 7 2 12310
. Incluye imprimir realmente la lista para la depuración. Impresiones5 even numbers 212 6 4 2 12310
(en líneas sep.)grep
fuera realmente más rápido quebash
. Hmm, me pregunto si hay una pregunta de codegolf donde podría publicar esa función bash: P