2011-06-23 14 views
6

Estoy trabajando en una secuencia de comandos para calificar una respuesta del usuario comparando dos matrices. (Es un cuestionario para ver qué tan bien saben la información palabra por palabra.) Ya tengo parte del código que necesito, como hacer que la respuesta del usuario sea minúscula y dividirla. Todo lo que necesito es algo para encontrar la cantidad de diferencias/errores. Por ejemplo:Usar JavaScript para calificar la respuesta del usuario (comparar dos matrices)

var correctanswer = ["The","quick","brown","fox","jumped","over","the","lazy","dog"]; 
var useranswer = ["The","brown","fox","jumped","up","and","over","the","really","lazy","cat"]; 
alert(counterrors(correctanswer, useranswer)); 

En este ejemplo en particular, se ejecuta la función Busco devolvería que el usuario hace 5 errores (se omite "rápida", añaden "arriba", "y" y "realmente", y ha cambiado "perro" por "gato"). Como puede ver, las dos matrices pueden ser de diferentes longitudes.

¿Alguien sabe cómo acercarse a esto? Pensaba que probablemente sería un ciclo como el siguiente:

for (x in correctanswer) { 
    // compare correctanswer[x] to useranswer[x]... not sure how exactly. Seems tricky... 
} 

¡Gracias por mirar esto! He visto la solución de diferencias de John Resig (http://ejohn.org/projects/javascript-diff-algorithm/) y otras cosas similares, e incluso algunas comparaciones de matriz, pero nada parecía funcionar, ya que las que encontré devuelven todas las diferencias, mientras que quiero ver cuántas diferencias hay. De nuevo, gracias por mirar y por favor háganme saber cualquier pregunta.

Actualización: ¡Muchas gracias a Magnar por la respuesta! Funcionó perfectamente.

Respuesta

6

lo que está después es la The Levenshtein Distance de las dos matrices.

Es un algoritmo que calcula el número de adiciones, deleciones y sustituciones necesarias para transformar una secuencia a otra.

El Wikipedia page I linked tiene una implementación de pseudo-código. He hecho una traducción línea por línea a JavaScript para usted:

var correctanswer = ["The","quick","brown","fox","jumped","over","the","lazy","dog"]; 
var useranswer = ["The","brown","fox","jumped","up","and","over","the","really","lazy","cat"]; 

console.log(calculate_levenshtein_distance(correctanswer, useranswer)); 

function calculate_levenshtein_distance(s, t) { 
    var m = s.length + 1, n = t.length + 1; 
    var i, j; 

    // for all i and j, d[i,j] will hold the Levenshtein distance between 
    // the first i words of s and the first j words of t; 
    // note that d has (m+1)x(n+1) values 
    var d = []; 

    for (i = 0; i < m; i++) { 
    d[i] = [i]; // the distance of any first array to an empty second array 
    } 
    for (j = 0; j < n; j++) { 
    d[0][j] = j; // the distance of any second array to an empty first array 
    } 

    for (j = 1; j < n; j++) { 
    for (i = 1; i < m; i++) { 
     if (s[i - 1] === t[j - 1]) { 
     d[i][j] = d[i-1][j-1];   // no operation required 
     } else { 
     d[i][j] = Math.min(
        d[i - 1][j] + 1,  // a deletion 
        d[i][j - 1] + 1,  // an insertion 
        d[i - 1][j - 1] + 1 // a substitution 
       ); 
     } 
    } 
    } 

    return d[m - 1][n - 1]; 
} 

Esto registrará 5 a la consola. Que es, como verá, la distancia correcta entre las matrices. El estudiante no agregó lazy. Entonces es 1 eliminación, 3 adiciones y 1 sustituciones.

+0

Magnar - ¡Gracias! Creo que esto es todo ... ¿Entonces pasaría los valores de matriz en lugar de las cadenas como lo hicieron en el artículo? – Alex

+0

Sí, en lugar de caracteres, usaría los valores de matriz; las palabras. – Magnar

+0

¡Muchas gracias por su ayuda! Todavía no soy muy bueno con JavaScript, pero trataré de tomarlo desde aquí. Si tiene alguna sugerencia sobre cómo implementar, hágamelo saber. Voy a marcar esto como la respuesta aceptada. – Alex

0

No estoy seguro si entiendo completamente lo que quiere, pero creo que esta es la solución.

function counterrors(a, b) { 
    var max = Math.max(a.length, b.length); 
    var min = Math.min(a.length, b.length); 
    var count = 0; 
    for (var i = 0; i < min; i+=1) { 
     if (a[i] !== b[i]) { 
      count += 1; 
     } 
    } 
    return count + max - min; // max - min for any extra things that don't match 
} 
var correctanswer = ["The", "quick", "brown", "fox", "jumped", "over", "the", "lazy", "dog"]; 
var useranswer = ["The", "brown", "fox", "jumped", "up", "and", "over", "the", "really", "lazy", "cat"]; 
alert(counterrors(correctanswer, useranswer)); 
+0

John - Gracias por compartir. Lo intenté y calculó 10 errores en lugar de 6 ... – Alex

+0

10 es el valor correcto si necesitan escribir las palabras en ese orden. ¿Estás tratando de averiguar cuántas palabras no escribió el usuario que están en la respuesta? Creo que Magnar tiene la solución que estás buscando. –

+0

Estoy tratando de encontrar el número de adiciones más eliminaciones más variaciones de palabras (como cambiar "perro" por "gato"). Entonces, no solo lo que no escribieron, sino también las cosas incorrectas que escribieron ... ¿Alguna otra idea? EDITAR: Acabo de ver la respuesta de Magnar. – Alex

Cuestiones relacionadas