3

у меня есть CSV-файл типа:Создание 2d булева массива в Java из данных таблицы

Event      Participant 
ConferenceA    John 
ConferenceA    Joe 
ConferenceA    Mary  
ConferenceB    John 
ConferenceB    Ted 
ConferenceC    Jessica 

Я хотел бы создать 2D булеву матрицу в следующем формате:

Event  John Joe Mary Ted Jessica 
ConferenceA 1  1 1  0 0 
ConferenceB 1  0 0  1 0 
ConferenceC 0  0 0  0 1 

Я начинаю с чтения в CSV-файл и использовать его для инициализации ArrayList типа:

AttendaceRecord(String title, String employee) 

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

+1

Этот CSV может иметь любое количество конференций и/или участников? – Andy

+0

Вставляя это в свой ArrayList, поддерживаете ли вы другие переменные, например, сколько разных сотрудников или событий у вас есть? –

+1

Почему бы просто не использовать «карту»? Ключами будут конференции, и значения будут участниками? Должен ли он быть «ArrayList»? Это будет намного проще для вас. – Andy

ответ

1

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

В вашем классе AttendanceRecord вам понадобятся следующие переменные экземпляра: два LinkedHashSet и один LinkedHashMap.LinkedHashSet # 1 будет хранить все конференции, а LinkedHashSet # 2 будет хранить всех участников. LinkedHashMap будет хранить конференции в качестве keys и участников list as values. Причина этого будет понятна через минуту. Сначала объясню, зачем вам нужен LinkedHashSet.

Цель LinkedHashSet

Обратите внимание, в вашем 2d массив строк (конференции) и колонны (участников) расположены в порядке их читать. Не только это, все дубликаты, прочитанные из файла, исчезли. Для сохранения порядка и устранения дубликатов LinkedHashSet идеально подходит для этой цели. Затем мы будем иметь отношение «один к одному» между позициями строк и позициями столбцов массива 2d и каждый LinkedHashSet через их представление массива. Давайте используем Jhon от ConferenceA, например. Jhon будет в позиции 0 в представлении массива участника Set и ConferenceA будет в позиции 0 в представлении массива конференции Set. Мало того, что размер каждого массива будет использоваться для определения размера вашего 2d массива (2darray [conferenceArrayLength] [participantArrayLength])

Цели в LinkedHashMap

Нам нужно LinkedHashMap, чтобы сохранить упорядочение элементов (следовательно, Linked). Элементы будут храниться внутри, как это.

ConferenceA :Jhon Joe Mary 
ConferenceB :Jhon Ted 
ConferenceC :Jessica 

Затем мы итерацию по структуре данных и отправить каждый keyvalue пару с функцией, которая возвращает позицию каждого элемента из каждого массива, возвращенный от каждого LinkedHashSet. По мере возврата каждой позиции строки и столбца мы добавим 1 в эту позицию в массив 2d.

Примечание: Я использовал массив Integer для моего примера, при необходимости замените.

AttendanceRecord.java

public class AttendanceRecord { 

    private Map<String, ArrayList> attendanceRecordMap = new LinkedHashMap<String, ArrayList>(); 
    private Set<String> participants = new LinkedHashSet<String>(); 
    private Set<String> conferences = new LinkedHashSet<String>(); 

    public AttendanceRecord() { 
    } 

    public Map<String, ArrayList> getAttendanceRecordMap() { 
     return attendanceRecordMap; 
    } 

    public Object[] getParticipantsArray() { 
     return participants.toArray(); 
    } 

    public Object[] getConferencesArray() { 

     return conferences.toArray(); 
    } 

    public void addToRecord(String title, String employee) { 

     conferences.add(title); 
     participants.add(employee); 

     if (attendanceRecordMap.containsKey(title)) { 
      ArrayList<String> tempList = attendanceRecordMap.get(title); 
      tempList.add(employee); 
     } else { 
      ArrayList<String> attendees = new ArrayList<String>(); 
      attendees.add(employee); 
      attendanceRecordMap.put(title, attendees); 
     } 
    } 
} 

Test.java

public class Test { 

    public static void main(String[] args) { 

     AttendanceRecord attendanceRecord = new AttendanceRecord(); 

     //There are hardcoded. You will have to substitute with your code 
     //when you read the file 
     attendanceRecord.addToRecord("ConferenceA", "Jhon"); 
     attendanceRecord.addToRecord("ConferenceA", "Joe"); 
     attendanceRecord.addToRecord("ConferenceA", "Mary"); 
     attendanceRecord.addToRecord("ConferenceB", "Jhon"); 
     attendanceRecord.addToRecord("ConferenceB", "Ted"); 
     attendanceRecord.addToRecord("ConferenceC", "Jessica"); 

     int[][] jaccardArray = new int[attendanceRecord.getConferencesArray().length][attendanceRecord.getParticipantsArray().length]; 
     setUp2dArray(jaccardArray, attendanceRecord); 
     print2dArray(jaccardArray); 
    } 

    public static void setUp2dArray(int[][] jaccardArray, AttendanceRecord record) { 
     Map<String, ArrayList> recordMap = record.getAttendanceRecordMap(); 

     for (String key : recordMap.keySet()) { 
      ArrayList<String> attendees = recordMap.get(key); 

      for (String attendee : attendees) { 
       int row = findConferencePosition(key, record.getConferencesArray()); 
       int column = findParticipantPosition(attendee, record.getParticipantsArray()); 
       System.out.println("Row inside " + row + "Col inside " + column); 
       jaccardArray[row][column] = 1; 
      } 
     } 
    } 

    public static void print2dArray(int[][] jaccardArray) { 
     for (int i = 0; i < jaccardArray.length; i++) { 
      for (int j = 0; j < jaccardArray[i].length; j++) { 
       System.out.print(jaccardArray[i][j]); 
      } 
      System.out.println(); 
     } 
    } 

    public static int findParticipantPosition(String employee, Object[] participantArray) { 
     int position = -1; 

     for (int i = 0; i < participantArray.length; i++) { 
      if (employee.equals(participantArray[i].toString())) { 
       position = i; 
       break; 
      } 
     } 
     return position; 
    } 

    public static int findConferencePosition(String employee, Object[] conferenceArray) { 
     int position = -1; 

     for (int i = 0; i < conferenceArray.length; i++) { 
      if (employee.equals(conferenceArray[i])) { 
       position = i; 
       break; 
      } 
     } 
     return position; 
    } 
} 
+0

Удивительное объяснение и демо для кого-то нового для «Карты» и «Установить»! Я уверен, что другие объяснения могут работать, но это очень четкая и хорошо объясненная реализация. Спасибо –

+0

Добро пожаловать. Извините за то, что вы дали весь ответ (я не думаю, что вы не против). Мне очень понравилась эта проблема, и я увлекся. Удачи :) – Andy

1

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

Затем вы создадите массив из этих булевых массивов (или список, что угодно).

Затем вы просто сортируете их, ищите T/F и печатаете соответствующие сообщения.

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

// For first row 
List labelStrings[]; 

labelStrings = {"Event", "John", "Joe", "Mary", "Ted", "Jessica"}; 

// For the matrix data 

// List to iterate horizontally EDIT: Made boolean! 
List<Boolean> strList= new ArrayList()<List>; 
// List to iterate vertically 
List<List> = listList new ArrayList()<List>; 

/* for all the entries in AttendanceRecord (watch your spelling, OP) 
    for all data sets mapping title to employee 
     add the row data to strList[entry_num] */ 

for (int i = 0; i < listList.size()-1; i++) 
    for (int j = 0; j < labelStrings.size()-1; j++) 
    { 
     if (i == 0) 
     System.out.println(strList[j] + "\t\n\n"); 
     else 
     { 
     // print listLists[i][j] 
     } 
    // iterate row by row (for each horizontal entry in the column of entries) 
    } 

Извините, я просто читаю комментарии сейчас.

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

+0

Я не думаю, что размер таблицы исправлен. Вот почему я попросил его убедиться. Опять же, мне это непонятно со своего поста. – Andy

+1

Это не сложно. Мое намерение состояло в том, чтобы предоставить полезную информацию OP, чтобы помочь ему на правильном пути. В этой теме есть удивительное отсутствие голосов в целом, сколько ответов есть. – jdero

+0

Я знаю, я не критиковал. – Andy

1

Попробуйте создать хэш-карту, содержащей

HashMap map = new HashMap<conferenceStr, HashMap<nameStr, int>>() 

Как вы итерацию через ArrayList, вы можете сделать что-то вроде

innerMap = map.get(conferenceStr) 
innerMap.put(nameStr, 1) 

, конечно, вы будете нуждаться в некоторой инициализации логике, как вы можете проверить если innerMap.get (nameStr) существует, если нет, перебирать все внутренние карты и innerMap.put (nameStr, 0)

Эта структура может быть использована для создания этого окончательного 2D-дуэта ean.

Разработка редактирования:

ArrayList<AttendanceRecord> attendanceList = new ArrayList<AttendanceRecord>(); 

// populate list with info from the csv (you implied you can do this) 

HashMap<String, HashMap<String, Integer>> map = new HashMap<String, HashMap<String, Integer>>(); 

//map to store every participant, this seems inefficient though 
HashMap<String, Integer>> participantMap = new HashMap<String, Integer>(); 

for (AttendanceRecord record : attendanceList) { 
    String title = record.getTitle(); 
    String employee = record.getEmployee(); 

    participantMap.put(employee, 0); 


    HashMap<String, Integer> innerMap = map.get(title); 
    if (innerMap == null) { 
    innerMap = new HashMap<String, Integer>(); 

    } 
    innerMap.put(employee, 1); 
} 

//now we have all the data we need, it's just about how you want to format it 

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

for (HashMap<String, Integer> innerMap : map.values()) { 
    for (String employee : participantMap.values()) { 

    if (innerMap.get(employee)) { 
     //print 1 
    } 
    else 
     //print 0 
    } 
} 
+1

Не уверен в уровне навыка OP, но, судя по его вопросу, этот подход может быть слишком большим (без обид, предназначенных для ОП, просто пытающихся помочь). Может быть, легче сломать его шагами для него, не так ли? вместо того, чтобы иметь «карту» в «карте». Тем не менее мне это нравится. – Andy

+0

@ Robert Можете ли вы подробнее рассказать об этом? –

+0

добавил некоторые разработки кода, дайте мне знать, если что-то запутать –

Смежные вопросы