2012-04-04 12 views
5

Estoy trabajando en una aplicación web que incluye listas largas de nombres. El cliente originalmente quería dividir los nombres en div s por letra, por lo que es fácil saltar a un nombre en particular en la lista.Listado por alfabeto, agrupa letras con pocas entradas juntas (PHP o JS)

Ahora, mirando la lista, el cliente señaló varias letras que tienen solo uno o dos nombres asociados a ellas. Ahora quiere saber si podemos combinar varias letras consecutivas si solo hay unos pocos nombres en cada una.

(Tenga en cuenta que las cartas sin nombres no se muestran en absoluto.)

lo que hago en este momento es que el servidor de base de datos devuelve una lista ordenada, a continuación, mantener una variable que contiene el carácter actual. Repaso la lista de nombres, incrementando el carácter e imprimiendo las etiquetas de apertura y cierre div y ul a medida que voy llegando a cada letra. Sé cómo adaptar este código para combinar algunas letras, sin embargo, una cosa de la que no estoy seguro es cómo una determinada combinación de letras es la mejor posible. En otras palabras, decir que tengo:

  • A - 12 nombres
  • B - 2 nombres
  • C - 1 Nombre
  • D - 1 Nombre
  • E - 1 Nombre
  • F - 23 nombres

Sé cómo terminar con un grupo A-C y luego tengo D por sí mismo. Lo que estoy buscando es una forma eficiente para darse cuenta de que A debe estar solo y luego B-D deben estar juntos.

No estoy seguro de por dónde empezar a buscar esto.

Si hace alguna diferencia, este código se utilizará en un módulo de Kohana Framework.


ACTUALIZACIÓN 2012-04-04:

Aquí es una aclaración de lo que necesito:

Diga el número mínimo de elementos que quiero en un grupo es de 30. Ahora dicen que la letra A tiene 25 elementos, letras B, C y D, tiene 10 elementos cada uno, y la letra E tiene 32 elementos. Quiero dejar a A solo porque será mejor combinar B + C + D. La forma simple de combinarlos es A + B, C + D + E, que no es lo que quiero.

En otras palabras, necesito el mejor ajuste que se acerque al mínimo por grupo.

+1

Aquí es un violín con una lista inicial de nombres si la gente quiere hacer algunas pruebas con un método mejorado js. http://jsfiddle.net/Avveb/ – mrtsherman

+0

Sé que esto se puede hacer con una gran programación dinámica, pero espero que alguien encuentre algo lo suficientemente simple como para ser utilizado en una aplicación web. Si necesito usar programación dinámica, tendré que ejecutarla de vez en cuando y almacenar en caché los resultados porque será demasiado intensa para ejecutar en la carga de la página. –

Respuesta

1

Si una letra contiene más de 10 nombres, o el límite razonable que establezca, no lo combine con el siguiente. Sin embargo, si comienzas a combinar letras, puedes ejecutarla hasta que se recopilen 15 o más nombres si quieres, siempre y cuando ninguna letra individual tenga más de 10. Esa no es una solución universal, pero es la forma en que la resolvería.

+0

Esto es probablemente lo que terminaré haciendo. Desafortunadamente, no es lo que esperaba hacer. –

0

Utilizando el jsFiddle que mrsherman dicho, se me ocurrió algo que podría funcionar: http://jsfiddle.net/F2Ahh/

Obviamente esto es para ser utilizado como un pseudocódigo, algunas técnicas para que sea más eficiente se podrían aplicar. Pero eso hace el trabajo.

+0

Eso no hace lo que quiero. Ya tengo un código que puede dividirlos así, simplemente agregando el siguiente grupo si este grupo es menor que el mínimo. Ver mi actualización a la pregunta. –

1

Se me ocurrió esta función usando PHP. Agrupa las letras que combinadas tienen más de $ nombres en ella.

function split_by_initials($names,$ammount,$tollerance = 0) { 
    $total = count($names); 
    foreach($names as $name) { 
     $filtered[$name[0]][] = $name; 
    } 
    $count = 0; 
    $key = ''; 
    $temp = array(); 
    foreach ($filtered as $initial => $split) { 
     $count += count($split); 
     $temp = array_merge($split,$temp); 
     $key .= $initial.'-'; 
     if ($count >= $ammount || $count >= $ammount - $tollerance) { 
      $result[$key] = $temp; 
      $count = 0; 
      $key = ''; 
      $temp = array(); 
     } 
    } 
    return $result; 
} 

la tercera parámetro se utiliza para cuando se desea limitar el grupo a una sola letra que no tiene el monto especificado, pero está lo suficientemente cerca.

Algo así como quiero dividir en grupos de 30 pero una tiene 25 a lo que, si se establece un tollerance de 5, A será dejado solo y se agruparán las otras letras.

Se me olvidó mencionar pero devuelve una matriz multidimensional con las letras que contiene como clave y luego los nombres que contiene. Algo así como

 
Array 
(
    [A-B-C-] => Array 
     (
      [0] => Bandice Bergen 
      [1] => Arey Lowell 
      [2] => Carmen Miranda 
     ) 
) 

No es exactamente lo que necesitábamos, pero creo que es lo suficientemente cerca.

0

JavaScrip Versión: versión con clase y símbolos de agrupación

function group_by_initials(names,ammount,tollerance) { 
     tolerance=tollerance||0; 
     total = names.length; 
     var filtered={} 
     var result={}; 
     $.each(names,function(key,value){ 
      val=value.trim(); 
      var pattern = /[a-zA-Z0-9&_\.-]/ 
      if(val[0].match(pattern)) { 
       intial=val[0]; 
      } 
      else 
      { 
       intial='sym'; 
      } 
      if(!(intial in filtered)) 
       filtered[intial]=[]; 

      filtered[intial].push(val); 
     }) 
     var count = 0; 
     var key = ''; 
     var temp = []; 
     $.each(Object.keys(filtered).sort(),function(ky,value){ 
      count += filtered[value].length; 
      temp = temp.concat(filtered[value]) 
      key += value+'-'; 
      if (count >= ammount || count >= ammount - tollerance) { 
       key = key.substring(0, key.length - 1); 
       result[key] = temp; 
       count = 0; 
       key = ''; 
       temp = []; 
      } 
     }) 
     return result; 
    } 
Cuestiones relacionadas