Estoy tratando de completar un ejercicio de codewars en el que simplemente devuelve una cadena de palabras en orden en función del número en la cadena.

Ejemplo:

order("is2 Thi1s T4est 3a") // should return "Thi1s is2 3a T4est"
order("4of Fo1r pe6ople g3ood th5e the2") // should return "Fo1r the2 g3ood 4of th5e pe6ople")

Este es mi intento hasta ahora:

function order(words) {
  let wordsArr = words.split(' ')
  let result = [];
  for (let i = 0; i < wordsArr.length; i++) {
    for (let j = 0; j < wordsArr[i].length; j++) {
      if (typeof wordsArr[i][j] === 'number') {
        result[wordsArr[i][j]] = wordsArr[i]
      }
    }
  }
  return result
}

Sin embargo, esto solo devuelve una matriz vacía. Mi lógica es que estoy recorriendo cada letra de cada palabra en wordsArr, y una vez que la letra typeof coincide con 'number', establezco el índice de matriz results de {{ X4}} igual a wordsArr[i]. Sin embargo, esto no funciona de la manera que esperaba, ¡y estoy desconcertado sobre por qué!

2
charlieyin 25 jun. 2020 a las 03:18

5 respuestas

La mejor respuesta

wordsArr[i][j] es un carácter, independientemente de si es numérico, por lo que debe verificar si es un dígito o no, lo que puede hacer con una coincidencia de expresiones regulares contra /\d/. Si es un dígito, agregue la palabra al resultado:

function order(words) {
  let wordsArr = words.split(' ')
  let result = [];
  for (let i = 0; i < wordsArr.length; i++) {
    for (let j = 0; j < wordsArr[i].length; j++) {
      if (wordsArr[i][j].match(/\d/)) {
        result[wordsArr[i][j]] = wordsArr[i]
      }
    }
  }
  return result.join(' ')
}

console.log(order("is2 Thi1s T4est 3a")) // should return "Thi1s is2 3a T4est"
console.log(order("4of Fo1r pe6ople g3ood th5e the2")) // should return "Fo1r the2 g3ood 4of th5e pe6ople")
2
Nick 25 jun. 2020 a las 00:26

Una solución más efectiva sería usar una expresión regular para apuntar al carácter numérico en cada palabra, luego convertir el número restante a un número real.

const a = order("is2 Thi1s T4est 3a")
const b = order("4of Fo1r pe6ople g3ood th5e the2")

console.log(a, b)

function order(words) {
  return words.split(' ')
    .map(w => ({word:w, n:Number(/\d+/.exec(w)[0])}))
    .sort((a, b) => a.n - b.n)
    .map(o => o.word)
}

Lo que esto hace es después de dividir la cadena, asigna cada palabra a un objeto que contiene la palabra y el número que contiene, convertido en un número real. Luego ordena la matriz mapeada en ese número y finalmente vuelve a mapear solo a la matriz de palabras, que se devuelve.

Se supone que cada palabra tendrá un número, por lo que no hay verificación para null en el .exec de la expresión regular.

1
slappy 25 jun. 2020 a las 00:26

Aquí hay un enfoque que utiliza una transformación simple.

const stripChars = word => word.replace(/[A-Za-z]+/g, '')

const xf = word => parseInt(stripChars(word), 10)

const order = words => words.split(' ').sort((a, b) => xf(a) - xf(b)).join(' ')

console.log(
  order('is2 Thi1s T4est 3a'),
)

console.log(
  order('4of Fo1r pe6ople g3ood th5e the2'),
)
1
richytong 25 jun. 2020 a las 00:38

Parece un buen caso para el uso de sort:

function order(str){
  const r = str.split(/\s+/);
  r.sort((a,b)=>{
    let m1 = a.match(/\d+/) || [a], m2 = b.match(/\d+/) || [b];
    return m1[0]>m2[0];
  });
  return r;
}
console.log(order('is2 Thi1s T4est 3a'));
console.log(order('4of Fo1r pe6ople g3ood th5e the2'));
console.log(order('a zebra now just2 another1 test3 b'));
1
StackSlave 25 jun. 2020 a las 00:56

Quizás otra solución en una línea:

  • Divide tu matriz.
  • Use sort(comparable) para reordenar elementos.
  • Convierte cada palabra en una matriz
  • Comprueba si hay un dígito.
  • Compare estos dígitos dentro de sort
  • Une las palabras (Elementos de una matriz)
  const order = str => str.split(" ").sort((a, b) => Array.from(a).find(e => 
  e.match(/\d/)) > Array.from(b).find(e => e.match(/\d/)) ? 1 : -1).join(" ")

  console.log(order("is2 Thi1s T4est 3a"))
  console.log(order("4of Fo1r pe6ople g3ood th5e the2"))
1
Menai Ala Eddine - Aladdin 25 jun. 2020 a las 00:51