2010-03-08 13 views
7

Siempre estoy luchando con algo como el siguiente ejemplo de Java:Cuando estoy iterando sobre dos matrices a la vez, ¿cuál uso como límite?

String breads[] = {"Brown", "White", "Sandwich"}; 
int count[] = new int[breads.length]; 
for (int i = 0; i < ****; i++) 
{ 
    // Prompt the number of breads 
} 

****: Array.length la que debe elegir?
Puedo elegir entre breads.length y count.length
Sé que sería el mismo resultado, pero no sé cuál elegir.

Hay muchos otros ejemplos en los que me sale el mismo problema.
Estoy seguro de que ha encontrado este problema también en el pasado.

¿Qué elegir? ¿Hay acuerdos generales?

Gracias

+1

por supuesto! ¡Gracias! –

+0

No estoy seguro de lo que estás preguntando. Sin saber cuál es el propósito de cada uno, es difícil decirlo (también, ¿quieres cargar tu conteo de matriz String con valores int?). –

+0

Su forma de hacer esto se llama usar "matrices paralelas". Como muchos han dicho, probablemente tenga más sentido usar un Mapa o algo así. Pero vea http://en.wikipedia.org/wiki/Parallel_array para una discusión sobre las ventajas y desventajas de su camino. – MatrixFrog

Respuesta

6

Creo que entiendo su pregunta.

La respuesta es que no use matrices.

En este caso, utilice un mapa de:

Map<String, Integer> breadCount = new TreeMap<String, Integer>(); 

breadCount.put("Brown", 0); 
breadCount.put("White", 0); 
breadCount.put("Sandwich", 0); 

Entonces sólo hay una "longitud", que es breadCount.size()

Ejemplo es en Java

+0

De manera similar, podrías crear una clase que capture tanto el valor String como el entero, así que de nuevo, hay es solo una colección (sé que el mapa de la clase no es una colección) – daveb

+0

El mapa no es una colección, pero puede hacer un ciclo "por cada" sobre él. Termina siendo un poco prolijo, pero está bien. 'for (Entrada entry: breadMap.entrySet()) {' ... y luego el nombre del pan es 'entry.getKey()' y el recuento es 'entry.getValue()'. – MatrixFrog

+0

No estoy de acuerdo. Un mapa solo tiene sentido cuando necesita poder buscar cosas en lugar de iterar en orden. De lo contrario, una matriz es más eficiente en el uso del espacio y es una buena estructura de datos del mínimo común denominador que es más probable que un mapa sea aceptado por las funciones genéricas de la biblioteca. – dsimcha

0

utilizar listas, conjuntos y mapas y foreach.

Si realmente tiene que usar matrices y no puede usar bucles foreach, no importa.

+1

Un bucle foreach no puede iterar sobre dos colecciones a la vez. –

+0

Es cierto, pero en muchos casos basta con agregar los elementos al final de una lista. En otros casos, usar los Elementos de las primeras Colecciones como claves y los valores de los segundos como valores en un Mapa funcionan bien. –

5

Usando breads.length es más precisa desde count tamaño depende de la longitud breads, pero aparte de que los diferentes resultados será el mismo .. y esto debe ser cierto siempre que se opere de una manera similar a la que usted escribió.

Si realmente no quiere ser annoyied por estas preguntas metafísicas puede utilizar una clase simple:

class Bread 
{ 
    String name; 
    int count 
} 

o puede utilizar una matriz multidimensional, o también un HashMap:

HashMap<String, Integer> counts 

por lo que puede iterar sobre la colección real, mientras que la recolección de los valores del mapa:

for (String b : breads) 
    System.out.println(b + " count: "+counts.get(b)); 
+0

No creo que "preciso" sea realmente la palabra correcta. Tal vez "directo". De todos modos, +1 para la clase de pan. Las matrices paralelas son una señal de que realmente desea una matriz de registros, y los objetos son la forma de hacer registros en un lenguaje OOP. –

+0

Sí, precisa no es la palabra correcta, pero el inglés no es mi lengua materna, así que no es * precisa * como lo sería :) – Jack

+0

El problema con hacer una clase para algo como esto es lo que sucede cuando quieres pasar cualquiera solo la matriz de pan o simplemente la matriz de conteo para una función de biblioteca genérica? Para interactuar con código genérico, casi siempre es más fácil trabajar con una matriz de primitivos en la mayoría de los lenguajes. – dsimcha

0

depende lo que está haciendo, pero en última instancia esto rara vez va a ser una decisión importante (ya que el valor es el mismo). Quizás te preocupes por problemas "más grandes". Para los intereses, en el JIT de .NET (no el compilador) puede detectar este patrón y eliminar el fuera de límites cheques, pero sólo si es algo obvio, como:

for(int i = 0 ; i < arr.Length ; i++) { 
    Console.WriteLine(arr[i]); // no bounds check if the JIT can prove it will 
           // never fail 
} 
1

En este escenario, yo iría con breads porque así es como se explicaría el código.

Lógicamente, está iterando sobre cada tipo de pan, no sobre el número de panes (aunque es el mismo).

Imagine que está explicando su código a otra persona, y use lo que sea lógico desde esa perspectiva. A veces ambos tienen sentido, en cuyo caso solo tienes que elegir arbitrariamente.

0

diría que elegir el "principal "array y usa su longitud en todos lados. De esta forma, su código es más claro y fácil de leer. Aparte de eso, creo que realmente no importa, porque count.length será el mismo y podrías mezclar estos dos a tu gusto.

0

Este problema parece bastante académico, pero en su caso, preferiría la matriz que intenta cambiar (contar), ya que cuando en algún caso (más bien académico), la duración del pan y el recuento deberían diferir , siempre es mejor no incurrir en problemas de límites de matriz ...

Aún podría haber una solución diferente: Tener solo una matriz que contenga estructuras con nombre ("panes" también podría denominarse "nombres de panes") y cuenta ...

+0

¿Por qué su enfoque previene problemas de límite de matriz? Para lograr eso, deberías usar algo como el mínimo de los dos largos. Lo cual consideraría ofuscación de código. –

+0

Porque me pareció que solo la matriz de conteo se usaría en el ciclo. "indicar el número de panes" - y (según entendí el problema) sería un bucle que ingresa los conteos ... por lo que solo se tocaría la matriz de conteo. – Juergen

1

En tal situación, declaro una variable local. De esta manera:

int n = breads.length; 
int[] count = new int[n]; 
for (int i = 0; i < n; i ++) { 
    // ... 
} 

Conceptualmente, esto significa que hago del "conteo de bucles" un valor en sí mismo. Un efecto secundario es que su problema está resuelto.

0

Intentaré evitar tener las diferentes matrices por completo. La mayoría de las veces, si tiene dos arrays que tienen el mismo tamaño en todo momento, en realidad está fingiendo un tipo compuesto o una relación.

// C++: inventory map: 
std::map< std::string, int > bread_inventory; 
bread_inventory["White"] = 0; 
bread_inventory["Brown"] = 0; 
bread_inventory["Sandwich"] = 0; 

// C++: complex type: 
struct bread_type 
{ 
    bread_type(std::string const & name, int calories) 
     : name(name), calories(calories) {} 
    std::string name; 
    int calories; 
}; 
std::vector<bread_type> v; 
v.push_back(bread_type("White", 100)); 
v.push_back(bread_type("Brown", 90)); 

Mediante el uso de tipos o contenedores de hormigón (en comparación con los elementos no relacionados en diferentes contenedores) se obtiene la coherencia de forma gratuita (menos se debe tener cuidado para verificar que ambos recipientes se actualizan de la misma manera) y algunas operaciones se vuelven mucho más simple (ordenar el vector por calorías puede implementarse trivialmente con una función de ordenamiento, mientras que si mantiene dos vectores separados para los nombres y los valores asociados, tendría que luchar para garantizar que las mismas operaciones se realicen en ambos contenedores).

El código también es más fácil de seguir y mantener ya que los tipos le dicen al programador lo que el escritor quería. Parte del conocimiento de la domai n que tiene al escribir la clase se pierde en su implementación. Su implementación se ocupa de una variedad de tipos de pan y una matriz de conteos, pero el código no le dice que, de hecho, son una sola entidad.

0

Está utilizando for(int i=0; i<array.length; i++) para repetir los valores de la matriz. Entonces realmente quiere usar array[i] y no otra cosa. En su caso, quiere iterar sobre los nombres que ha definido. Sin embargo, la matriz de conteos está llena de ceros y la pregunta es por qué desea iterar sobre ellos. Por lo tanto, si escribe

String breads[] = {"Brown", "White", "Sandwich"}; 
int count[] = new int[breads.length]; 
for (int i = 0; i < breads.length; i++) { 
} 

, verá claramente que el ciclo es para repetir los nombres. Y lidias con estos nombres (como mostrarlos). Pero si se escribe

String breads[] = {"Brown", "White", "Sandwich"}; 
int count[] = new int[breads.length]; 
for (int i = 0; i < count.length; i++) { 
} 

La pregunta se elevan ¿Por qué quiere iterar sobre los valores de cuenta? todos son 0. El flujo de datos en realidad es algo así como count_value = f(bread_value), los nombres de los pan son independent variable. Se puede escribir (en Java)

String breads[] = {"Brown", "White", "Sandwich"}; 
int count[] = new int[breads.length]; 
for (String bread: breads) { 
} 

y ve claramente que se preocupa por los nombres de pan y quiere hacer algo con ellos. Que desee establecer los recuentos son solo un efecto secundario del ciclo, pero no controla los tiempos de las iteraciones.

Cuestiones relacionadas