Динамическое именование переменной (E1, E2, E3 …)

#java #oop #arraylist

Вопрос:

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

У меня есть список объектов, в котором у каждого объекта есть имя.

Список всегда должен быть уникальным и содержать не более 5 элементов, таких как [E1,E2,E3]

Если, например, список имеет начальную форму [E3,E5] , и я добавляю объект, его имя должно быть E1, и список будет [E1,E3,E5] или [E3,E5,E1] это не имеет значения, если имя уникально и элемент добавляется в список, начиная с 1 до 5.

Если добавить еще один элемент, он должен быть [E3,E5,E1,E2] , всегда с уникальным именем и между 1 и 5

Это мои неудачные попытки,

 StartNode node = new StartNode(); node.setName("E1");  for (int i = 0; i lt; circuit.getNbStartNodes(); i  ) {  for (int j = 1; j lt;= circuit.getNbStartNodes(); j  ) {  String test = ((StartNode) circuit.getStartNode(j)).getName();  if (("E" j).equalsIgnoreCase(test) amp;amp; ("E" j).equalsIgnoreCase(node.getName()) ) {  break;  }  else  node.setName("E"   j);  } }  /*while (t lt;= circuit.getNbStartNodes()) {  for (int j = 0; j lt; circuit.getNbStartNodes(); j  ) {  String test = ((StartNode) circuit.getStartNode(j)).getName();  if (("E"   t).equalsIgnoreCase(test) || ("E"   t).equalsIgnoreCase(node.getName()))  break;  else {  node.setName("E"   t);  }  }  t  ;  } */  /* for (int i = 1; i lt;= circuit.getNbStartNodes(); i  ) {  for (int j = 0; j lt; circuit.getNbStartNodes(); j  ) {  String test = ((StartNode) circuit.getStartNode(j)).getName();  if (!("E"   i).equalsIgnoreCase(test)) {  node.setName("E"   i);  t=0;  break;  }  }  if (t==0)  break;  else  continue; */ //String test = ((StartNode) circuit.getStartNode(i)).getName(); //for (int j = 1; j lt;= circuit.getNbStartNodes(); j  ) { // if (!("E"   j).equalsIgnoreCase(test)) // node.setName("E"   j); //}  

Что я сделал не так в своем коде?

Комментарии:

1. Мне было интересно, содержит ли ваш первоначальный список E3 и E5 имеет ли значение , какой элемент будет добавлен? Должно ли это быть E1 , или что-то из E1 этого , E2 или E4 нормально?

Ответ №1:

  • Создайте небольшой логический массив, чтобы отслеживать, какие имена уже используются, и соответствующим образом заполните его
  • Найдите первый неиспользуемый элемент и используйте его в качестве идентификатора.
 boolean[] used = new boolean[circuit.getNbStartNodes()];  for (int i = 0; i lt; used.length; i  ) {  int index = Integer.parseInt(((StartNode) circuit.getStartNode(j)).getName().substring(1)) - 1; // should be in range 0..4  used[index] = true; }  String name = "E"; for (int i = 0; i lt; used.length; i  ) {  if (!used[i]) {  name  = String.valueOf(i   1); // starting from 1  break;  } } System.out.println("free name: "   name); StartNode node = new StartNode(); node.setName(name);  // add new node to circuit, etc.  

Комментарии:

1. если, например, все используемые значения являются истинными, второй цикл не выполняется, как вы думаете, могу ли я инициировать массив логических значений, содержащий мои уже существующие узлы, которые превратятся в true, а остальные будут оставлены как ложные, таким образом, будет выполнен второй цикл ? также я думаю, что он отсутствует for (int j = 0; j lt; circuit.getNbStartNodes(); j ) { для первого цикла

2. Идея used состоит в том, чтобы отслеживать, какие узлы используются, по умолчанию используются все элементы этого массива false . Если после первого цикла не останется свободного места, второй цикл все равно запустится. Размер used совпадает с circuit.getNbStartNodes() , поэтому не имеет значения, какое значение следует использовать в первом цикле (нет необходимости вызывать метод, если есть равный used.length ).

Ответ №2:

При небольших значениях решение Алекса работает нормально.

Однако, если вы когда-нибудь столкнетесь с вариантом использования, когда количество элементов станет потенциально большим, вы можете использовать a TreeSet для отслеживания неиспользуемых чисел. Кроме того, nextCeilValue это следующий номер, который нужно выбрать, когда нет удаленных номеров.

В приведенном ниже коде я создал UniqueNumber класс, который способен к get следующему номеру или remove заданному номеру. Обратите внимание, что этот код содержит целые числа, начинающиеся с 0. Конечно, вы можете легко преобразовать это в свои электронные номера, используя функцию i -gt; "E" (i 1) .

 public class UniqueNumber {   private int nextCeilValue;   private final TreeSetlt;Integergt; removedNumbers = new TreeSetlt;gt;(Integer::compare);   public int get() {  if (removedNumbers.isEmpty()) {  return nextCeilValue  ;  }  else {  int number = removedNumbers.first();  removedNumbers.remove(number);  return number;  }  }   public boolean remove(int number) {  if (number lt; 0 || number gt; nextCeilValue) {  return false;  }   if (number == nextCeilValue) {  nextCeilValue--;  }  else {  removedNumbers.add(number);  }  return true;  }   public int size() {  return nextCeilValue - removedNumbers.size();  } }  

Чтобы проверить это, нам сначала нужно смоделировать вашу начальную ситуацию. В нашем мире целых чисел, начинающемся с нуля, нам нужны числа 2 и 4 (представляющие E3 и E5). В приведенном ниже коде нам нужно вызвать get пять раз, а затем удалить элементы 0, 1 и 3. Конечно, мы могли бы создать UniqueNumber(int... initialValues) конструктор, который делает это под капотом.

 UniqueNumber un = new UniqueNumber(); for (int i = 0; i lt; 5; i  ) {  un.get(); } un.remove(0); // Remove E1 un.remove(1); // Remove E2 un.remove(3); // Remove E4  

Чтобы получить следующее значение, просто используйте это:

 StartNode node = new StartNode(); node.setName("E"   (un.get()   1));  

Комментарии:

1. спасибо, сэр, я использую этот для своих ворот, так как у меня будет максимум 50 ворот.