Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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?

share|improve this question
1  
This CSV can have any number of conferences and/or participants ? –  Andy Jul 11 '13 at 17:29
    
When inserting this into your ArrayList, are you maintaining other variables like how many different employees or events you have? –  Saviour Self Jul 11 '13 at 17:30
1  
Why not just use a Map ? The keys will be the conferences and the values will be the participants ? Does it have to be an ArrayList ? This will be much easier for you to do. –  Andy Jul 11 '13 at 17:30
    
@SaviourSelf I am not maintaining that information though it is probably a good idea. Ultimately, this data will come from a db. Iam just prototyping with a csv –  Brian Vanover Jul 11 '13 at 17:51
    
@Andy It does not have to be an ArrayList. I have very little experience with Maps, but I am open to that implementation –  Brian Vanover Jul 11 '13 at 17:52

3 Answers 3

up vote 1 down vote accepted

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;
    }
}
share|improve this answer
    
Awesome explanation and demo for someone new to 'Map' and 'Set'! I'm sure the other explanations may work as well but this is a very clear and well explained implementation. Thank You –  Brian Vanover Jul 12 '13 at 15:59
    
You are welcome. Sorry for giving the whole answer (I don't think you mind though). I liked that problem a lot and I got carried away. Good luck :) –  Andy Jul 12 '13 at 17:26

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
  }
}
share|improve this answer
1  
Not sure of OP skill level but judging by his question this approach might be a little too much (no offense intended OP just trying to help). Might be easier to break it in steps for him don't you think ? instead of having a Map within a Map. Still I like this. –  Andy Jul 11 '13 at 17:52
    
@Robert Can you elaborate on this a little more? –  Brian Vanover Jul 11 '13 at 20:20
    
added some code elaboration, let me know if anything's confusing –  Robert Chuchro Jul 11 '13 at 21:18

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.

share|improve this answer
    
I don't think the table size is fixed. That's why I asked him to make sure. Then again, it's not clear to me from his post. –  Andy Jul 11 '13 at 17:53
1  
It's not a hard fix either way. My intention was to provide useful information to the OP to help set him on the right track. This thread has a surprising lack of votes in general, for how many responses there are. –  jdero Jul 11 '13 at 18:55
    
I know, I wasn't criticizing. –  Andy Jul 11 '13 at 19:01
    
@jdero This table size will change over time as more events and attendances are added –  Brian Vanover Jul 11 '13 at 20:31
    
Then just use the ArrayList. You can adjust your ouput as your List grows etc. –  jdero Jul 11 '13 at 20:52

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.