Question

I have a .csv file of type:

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

I would like to create a 2D boolean matrix of the following format:

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

I start by reading in the csv and using it to initialize an ArrayList of type:

AttendaceRecord(String title, String employee)

How can I iterate through this ArrayList to create a boolean matrix like the one above in Java?

Was it helpful?

Solution

This is the easiest way I can think of for you. This answer can certainly be improved or done in a completely different way. I'm taking this approach because you mentioned that you are not completely familiar with Map (I'm also guessing with Set). Anyway let's dive in.

In your AttendanceRecord class you are going to need the following instance variables: two LinkedHashSet and one LinkedHashMap. LinkedHashSet #1 will store all conferences and LinkedHashSet #2 will store all participants. The LinkedHashMap will store the the conferences as keys and participants list as values. The reason for this will be clear in a minute. I'll first explain why you need the LinkedHashSet.

Purpose of LinkedHashSet

Notice in your 2d array, the rows (conferences) and columns (participants) are arranged in the order they were read. Not only that, all duplicates read from the file are gone. To preserve the ordering and eliminate duplicates a LinkedHashSet fits this purpose perfectly. Then, we will have a one-to-one relationship between the row positions and the column positions of the 2d array and each LinkedHashSet via their array representation. Let's use Jhon from ConferenceA for example. Jhon will be at position 0 in the array representation of the participant Set and ConferenceA will be at position 0 in the array representation of the conference Set. Not only that, the size of each array will be used to determine the size of your 2d array (2darray[conferenceArrayLength][participantArrayLength])

Purpose of the LinkedHashMap

We need the LinkedHashMap to preserve the ordering of the elements (hence Linked). The elements will be stored internally like this.

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

We will then iterate through the data structure and send each key value pair to a function which returns the position of each element from each array returned from each LinkedHashSet. As each row and column position is returned, we will add a 1 to that position in the 2d array.

Note: I used an Integer array for my example, substitute as needed.

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;
    }
}

OTHER TIPS

Basically you'll want to start by searching through your input strings to find each of the names (String.contains) and set a boolean array of each field name.

Then you'll make an array of those boolean arrays (or a list, whatever).

Then you simply sort through them, looking for T/F and printing corresponding messages.

I included some very rough pseudocode, assuming I am understanding your problem correctly.

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

Sorry, I'm just reading through the comments now.

You'll definitely want to arrange your data in a way that is easy to iterate through. Since you have a fixed table size, you could hardcode a boolean array for each entry and then print on validation they were mapped to the event as indicated in your input string.

Try creating a hash map containing

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

As you iterate through your ArrayList, you can do something like

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

of course you'll need some initialization logic, like you can check if innerMap.get(nameStr) exists, if not, iterate over every inner map and innerMap.put(nameStr, 0)

This structure can be used to generate that final 2D boolean matrix.

Elaboration edit:

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 example if you wanted to just print out a table like that you could iterate through every element of map doing this:

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

    if (innerMap.get(employee)) {
      //print 1
    }
    else 
      //print 0
  }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top