Когда я выполняю итерации более чем двух массивов сразу, какой я использую в качестве предела?

Я всегда борюсь с чем-то как следующий пример Java:

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

****: какой array.length я должен выбрать?
Я могу выбрать между breads.length и count.length
Я знаю, что это был бы тот же результат, но я не знаю, какой я shoud выбирают.

Существует много других примеров, где я получаю ту же проблему.
Я уверен, что Вы встретились с этой проблемой также в прошлом.

Что необходимо выбрать? Есть ли генеральные соглашения?

Спасибо

7
задан Martijn Courteaux 8 March 2010 в 19:18
поделиться

10 ответов

Думаю, я понял ваш вопрос.

Ответ: не используйте массивы.

В этом случае используйте карту:

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

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

Тогда есть только одна «длина», которая равна breadCount.size ()

Пример в Java

6
ответ дан 6 December 2019 в 19:36
поделиться

В этом сценарии я бы выбрал хлебов , потому что именно так вы объясняете код.

Логично, что вы перебираете каждый вид хлеба, а не количество хлеба (хотя это одно и то же).

Представьте, что вы объясняете свой код кому-то другому, и используете все, что имеет смысл с этой точки зрения. Иногда оба имеют смысл, и в этом случае вам просто нужно выбирать произвольно.

1
ответ дан 6 December 2019 в 19:36
поделиться

Это зависит от того, что вы делаете, но в конечном итоге это редко будет важным решением (поскольку значение то же самое) . Возможно, беспокоятся о «более серьезных» проблемах. Для интереса, в .NET JIT (, а не компилятор) может обнаружить этот шаблон и исключить проверки выхода за границы, но только если это очевидно, например:

for(int i = 0 ; i < arr.Length ; i++) {
    Console.WriteLine(arr[i]); // no bounds check if the JIT can prove it will
                               // never fail
}
0
ответ дан 6 December 2019 в 19:36
поделиться

Вы используете for(int i=0; i для перебора значений массива. Поэтому на самом деле вы хотите использовать array[i], а не что-то другое. В вашем случае вы хотите выполнять итерации по именам, которые вы определили. Массив count, однако, заполнен нулями, и вопрос в том, почему вы хотите итерироваться по ним. Так что если вы напишете

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

вы ясно увидите, что цикл предназначен для итерации по именам. И вы работаете с этими именами (например, показываете их). Но если вы напишете

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

Возникает вопрос почему вы хотите перебирать значения count? Они все равны 0. На самом деле поток данных выглядит примерно так count_value = f(bread_value), названия хлеба - независимая переменная. Вы можете написать (на Java)

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

и явно видите, что вас волнуют имена хлебов и вы хотите что-то с ними сделать. То, что вы хотите установить counts - это просто побочный эффект цикла, но он не контролирует время итераций.

0
ответ дан 6 December 2019 в 19:36
поделиться

Я бы попытался вообще не использовать разные массивы. Чаще всего, если у вас есть два массива, которые всегда имеют одинаковый размер, вы фактически имитируете составной тип или отношение.

// 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) );

Используя конкретные типы или контейнеры (по сравнению с несвязанными элементами в разных контейнерах), вы бесплатно получаете согласованность (нужно меньше заботиться о том, чтобы убедиться, что оба контейнера обновляются одинаково), а некоторые операции становятся намного проще (упорядочивание вектор по калориям можно тривиально реализовать с помощью функции упорядочения, тогда как если вы сохраните два отдельных вектора для имен и связанных значений, вам придется бороться за свой путь, чтобы гарантировать, что одни и те же операции выполняются на обоих контейнерах.

код также легче отслеживать и поддерживать, поскольку типы сообщают программисту, чего хочет писатель. Часть знаний о предметной области, которые вы имеете при написании класса, теряется в вашей реализации. Ваша реализация имеет дело с массивом типов хлеба и один массив счетчиков, но код не говорит вам, что они на самом деле являются одним объектом.

0
ответ дан 6 December 2019 в 19:36
поделиться

Использование breads.length является более точным , поскольку count размер зависит от хлеба длины, но, кроме этого, разные результаты будут быть таким же .. и это должно быть правдой, когда вы действуете способом, подобным тому, который вы написали.

Если вы действительно не хотите, чтобы вас раздражали эти метафизические вопросы, вы можете использовать простой класс:

class Bread
{
    String name;
    int count
}

или вы можете использовать многомерный массив, или также хэш-карту:

HashMap<String, Integer> counts

, чтобы вы могли повторять реальную коллекцию при сборе значений с карты:

for (String b : breads)
   System.out.println(b + " count: "+counts.get(b));
5
ответ дан 6 December 2019 в 19:36
поделиться

В такой ситуации я объявляю локальная переменная. Примерно так:

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

Концептуально это означает, что я делаю «счетчик цикла» самостоятельным значением. Побочный эффект - ваша проблема решена.

1
ответ дан 6 December 2019 в 19:36
поделиться

Я бы сказал, выберите «основной» массив и везде используйте его длину. Таким образом ваш код будет более понятным и легким для чтения. В остальном, я думаю, это не имеет особого значения, потому что count.length будет таким же, и вы можете смешивать эти два, как хотите.

0
ответ дан 6 December 2019 в 19:36
поделиться

Эта проблема выглядит скорее академичной - но в вашем случае я бы предпочел массив, который вы намереваетесь изменить (подсчитать), поскольку, когда в некотором (скорее академическом) случае длина хлеба и количество должны различаться, Всегда лучше не сталкиваться с проблемами, связанными с границами массива ...

Тем не менее, может быть другое решение: иметь только один массив, содержащий структуры с именем («хлебцы» можно также назвать «имя хлеба») и подсчитывать. ..

0
ответ дан 6 December 2019 в 19:36
поделиться

Использовать списки, наборы и карты и петли foreach.

Если вам действительно нужно использовать массивы и нельзя использовать циклы foreach, это не имеет значения.

0
ответ дан 6 December 2019 в 19:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: