How to create an array of arraylists with stringlists inside?

edited April 2015 in How To...

I'm getting data from an txt file and each line of that txt is transformed into a stringlist. Each time there are stringlists that are equal, a group is created with that stringlists. This "group" is going to be added to an arraylist. This is what I have so far.

What I want to do is get all this "groups"(arraylists) into an array, so I can access all groups, and all individual strings of the stringslists.

Something like this:

This is my code:

int contador = 0;
StringList lista = new StringList();
Via [] listv;
ArrayList <Via> listaVias;
Via ultimaVia=null;
ArrayList <Via>listV=new ArrayList();
ArrayList [] todos = new ArrayList[100];

void setup() {
  size(1200, 700);

  String lines [] = loadStrings("data.txt");
  for (String linha : lines) {

    String[] params = split(linha, TAB);
    float score = parseFloat(params[0]);
    Via via = new Via(score);

    for (int i=2; i<params.length; i++) {
      via.append(params[i]);
    }
    if (via.size()>3) {

      if (ultimaVia!=null && ultimaVia.isEqual(via)) {        
        for(int i=0; i<100;i++){
        listaVias=new ArrayList();
        todos[i].add(listaVias);
        listaVias.add(via);
        //println(listaVias.get(0));

        }

      } else {
        contador++;
        println(contador);

        if (contador==100) {
          break;
        }
      }
    }

    ultimaVia = via;
  }
}

This is my class Via:

`class Via extends StringList {

  final float score;

  Via(float score) {
    super();
    this.score = score;
  }

  boolean isEqual(Via via) {
    if (this.size() == via.size()) {
      for (int i=1; i<via.size();i++) {
        if(!via.get(i).equals(this.get(i))){
          return false;
        }
      }
    } else {
      return false;
    }
    return true;
  }
}
`

SAMPLE OF TXT

Answers

  • Can you fix your code so that we can read it? Just highlight all your code and press the code button.

    Also, what exactly is your question? What does this code do? What did you expect instead?

  • My code is giving me the error NullPointerException at line 27. I want to call todos[5] (for example) to get the arraylist saved in that index, containing equal stringlists.

  • Keep in mind that an array of Objects (such as ArrayList) starts out with null values in every index.

    If you want an empty ArrayList in each index, then you'll have to initialize every index of that array. Here's an example that uses an array of Strings:

    String[] strArray = new String[10];
    println(strArray[0]); //prints out null
    for(int i = 0; i < strArray.length; i++){
       strArray = "testing";  //initialize the index
    }
    println(strArray[0]);
    
  • I dont want an empty ArrayList in each index. In each index I want an ArrayList filled with lines of the txt, each line being a Via (that is a StringList).

  • Each time there are stringlists that are equal, a group is created with that stringlists.

    err....

    so you want to save 7 times the same stringlist in a group...?

    is this part of a bigger project?

    Because otherwise, why not save the same stringlist only once (and make a note how often it occured) ?

    ;-)

  • Answer ✓

    before line 27 say

    todos[i] = new ArrayList(); 
    
  • I dont want an empty ArrayList in each index. In each index I want an ArrayList filled with lines of the txt, each line being a Via (that is a StringList).

    To fill an ArrayList with something, you must first start with an empty ArrayList.

    (that sounds like an ancient proverb)

  • It is part of a bigger project and its not exactly the same stringlist. Just said that to simplify it. They are only different in the first String. What we want to do is save this groups that only differ in the first element.

    Sorry for the lack of explanation.

  • edited April 2015

    To start with something, you first must empty your mind, young padawan.

    unlearn what you've learned.

  • before line 27 say todos[i] = new ArrayList();

    Chrisir I did this it gives me the error :

  • edited April 2015

    Ok I changed todos[i].add(listaVias) to todos[i]=listaVias.

    It is now running but it doesnt print anything. I put a println("hi") before the for where todos[i]=listaVias is . It is not printing...

  • edited April 2015
    • I've made an effort to follow up the development of your solution so far, but it's too confusing...
    • So instead I've turned to understand the reason for your class Via and why it extends StringList.
    • AFAIK, you extract the 1st column as a float value and stores that in score.
    • Ignores 2nd & 3rd columns. And only considers from 4th column & forward as the "unique" StringList.
    • And in order to query about it, you've implemented a method called isEqual().
    • And inexplicably you wish to collect repeated StringList + float, as customized Via class, into ArrayList containers.
    • And finally have 1 array to hold them all! :D

    Since the float values from the 1st column are stored apart and don't take part inside isEqual(), I think what you're really looking for is a way to map unique StringList (3rd column and on) instances to a set of unique Float values. :-?

    In short, you want this very complex arrangement: Map<HashableStringList, Set<Float>> ^#(^

    • Processing's StringList class can't be a key value for maps nor sets, b/c it doesn't implement equals() nor hashCode().
    • You've made an effort in your class Via by implementing isEqual().
    • Problem is that Java classes like HashMap & HashSet don't recognize self-made methods.
    • We've gotta @Override Object's equals() & hashCode() instead.
    • Therefore I've also created a StringList derived class, very similar to your Via, called HashableStringList just for that.
    • The idea is to collect Float values from your file, store them in a HashSet, and map them back to some unique HashableStringList instance.
    • In the end, you've got a collection of unique StringList keys mapped to a set of Float values.
    1. https://processing.org/reference/StringList.html
    2. https://processing.org/reference/HashMap.html
    3. http://docs.oracle.com/javase/8/docs/api/java/util/Map.html
    4. http://docs.oracle.com/javase/8/docs/api/java/util/Set.html
    5. http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html

    Warning: Since I don't have your "data.txt" TSV file, I can't run & determine if the program is correct! :-\"

    /**
     * HashableStringList Class (v1.2)
     * by GoToLoop (2015/Apr/20)
     *
     * forum.processing.org/two/discussion/10419/
     * how-to-create-an-array-of-arraylists-with-stringlists-inside
     */
    
    import java.util.Map;
    import java.util.Set;
    import java.util.HashSet;
    
    Map<HashableStringList, Set<Float>> all;
    
    void setup() {
      all = loadData("data.txt", TAB, 3);
      println(all);
      exit();
    }
    
    Map<HashableStringList, Set<Float>> loadData(String path, char delim, int idx) {
      String[] lines = loadStrings(path);
    
      Map<HashableStringList, Set<Float>> m;
      m = new HashMap<HashableStringList, Set<Float>>(lines.length>>2, .9);
    
      for (String s : lines) {
        String[] cols = split(s, delim);
        HashableStringList k = new HashableStringList(idx, cols);
    
        Set<Float> v = m.get(k);
        if (v == null)  m.put(k, v = new HashSet<Float>());
        v.add(float(cols[0]));
      }
    
      return m;
    }
    
    class HashableStringList extends StringList implements java.util.RandomAccess {
      HashableStringList() {
        super();
      }
    
      HashableStringList(int len) {
        super(len);
      }
    
      HashableStringList(String... s) {
        super(s);
      }
    
      HashableStringList(int idx, String... s) {
        super(subset(s, idx));
      }
    
      HashableStringList(Iterable<String> iter) {
        super(iter);
      }
    
      @ Override int hashCode() {
        StringBuilder sb = new StringBuilder();
        for (String s : values())  sb.append(s);
        return sb.toString().hashCode();
      }
    
      @ Override boolean equals(Object o) {
        if (o == this)  return true;
        if (!(o instanceof StringList))  return false;
    
        StringList other = (StringList) o;
        if (other.size() != size())  return false;
    
        int idx = 0;
        for (String s : other.values())  if (!s.equals(get(idx++)))  return false;
    
        return true;
      }
    }
    
  • @GoToLoop: As we've discussed previously, please do not post full-code solutions. This is not helpful. Instead, try understanding OP's misunderstanding and walk them through the process of solving the problem.

  • @GoToLoop so every "group" has a unique float? How to get the group with a specific float?

  • edited April 2015
    • Hello again! I've been trying to figure out the relationship of each entry from "data.txt"'s image.
    • It's unfortunate you haven't provided us at least a small sample of that TSV file though!
    • Cautiously I thought that each unique StringList could end up w/ more than 1 float value.
    • But as far as that picture shows, it seems like that each unique StringList has 1 float only and vice-versa.
    • Another issue is that in my attempt solution, I've discarded all of the String present in the 3nd column.
    • And you seem to be interested in having the float value as the key in the Map rather than the StringList.

    • This time, I'm making more strict assumptions...
    • There's only 1 float for each StringList. And vice-versa.
    • It is obvious that a float can't hold such big value. Changed it to double.
    • Since the StringList doesn't change once read from the file, changed it to a simple String[].
    • Therefore we've got a Map<Double, String[]> container to represent the relationship between the unique Double values w/ its unique String[] array.
    • That String[] represents all the String taken from the 4th column and forward as it was before.
    • That still leaves us w/ the discarded String from the 3rd column.
    • In order to account for that, there's gonna be a companion Map just to store a Set full of unique 3rd column String related to 1 Double value.
    • So here's the container for it: Map<Double, Set<String>>.
    • I've also copied some of the rows from the picture as "table.tsv":


        0.9999973201094007  6   AP1S1   TP53    USP7    DAXX    SUM01   PCNA
        0.9999973201094007  6   VEGFB   TP53    USP7    DAXX    SUM01   PCNA
        0.999997281834667   9   SIT1    RELA    NFKBIA  BTRC    SKP1    CUL1    SKP2    CDKN1B  CCND3
        0.9999972662560181  4   ID3 APC CTNNB1  EP300
        0.9999972662560181  4   SNRNP70 APC CTNNB1  EP300
        0.9999972662560181  4   UHRF1   APC CTNNB1  EP300
    
    • 3 unique Double mapped to 3 unique String[] gonna be recognized and stored as a (key, value) pair in the Map.
    • I've chosen TreeMap as the implemented class for both Map containers.
    • TreeMap provides sorted order presentation for the key entries:
      http://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html
    • But if you prefer losing that in favor for some more performance, you may replace it w/ regular HashMap though.
    • Please tell us if it works for ya and whether that's what you intended.
    • W/o further ado, here's the 2nd attempt incarnation: :D


    /**
     * Double to String TreeMaps (v1.13)
     * by GoToLoop (2015/Apr/21)
     *
     * forum.processing.org/two/discussion/10419/
     * how-to-create-an-array-of-arraylists-with-stringlists-inside
     */
    
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.TreeMap;
    
    import java.util.Set;
    import java.util.HashSet;
    
    final Map<Double, String[]>    double_to_string_array   = new TreeMap<Double, String[]>();
    final Map<Double, Set<String>> double_to_string_hashset = new TreeMap<Double, Set<String>>();
    
    void setup() {
      loadTSVData("table.tsv", 3, 2, double_to_string_array, double_to_string_hashset);
    
      for (Entry<Double, String[]> pair : double_to_string_array.entrySet()) {
        print(pair.getKey(), "\t= ");
        println(pair.getValue());
      }
    
      println();
      printMapData(double_to_string_hashset);
    
      exit();
    }
    
    static final <K, V> void printMapData(Map<K, V> mapData) {
      for (Entry<K, V> pair : mapData.entrySet()) {
        print(pair.getKey(), "\t= ");
        println(pair.getValue());
      }
    }
    
    void loadTSVData(String path, int seq_idx, int str_idx,
                     Map<Double, String[]> dsa, Map<Double, Set<String>> dsh)
    {
      for (String s : loadStrings(path)) {
        String[] cols = splitTokens(s);
        if (cols == null || cols.length <= max(seq_idx, str_idx))  continue;
    
        Double k = Double.valueOf(cols[0]);
        Set<String> v = dsh.get(k);
    
        if (v == null) {
          dsa.put(k, subset(cols, seq_idx));
          dsh.put(k, v = new HashSet<String>());
        }
    
        v.add(cols[str_idx]);
      }
    }
    
  • edited April 2015

    A more complete & strict alternative version to loadTSVData() w/ more error checks. >:/
    B/c it's much bigger, I thought it'd be better to post it apart here and leave the smaller version above for easier comprehension! :-B

    void loadTSVData(String path, int seq_idx, int str_idx,
                     Map<Double, String[]> dsa, Map<Double, Set<String>> dsh)
    {
      int min_size = max(seq_idx = abs(seq_idx), str_idx = abs(str_idx));
    
      for (String s : loadStrings(path)) {
        String[] cols = splitTokens(s);
        if (cols == null || cols.length <= min_size) {
          System.err.println("# of valid entries in this loaded row data:");
          println(cols);
          delay(1);
          System.err.println("is less than min. expected size of " + (min_size + 1) + "!\n");
          delay(1);
          continue;
        }
    
        Double k;
        try {
          k = Double.valueOf(cols[0]);
        } catch (NumberFormatException nfe) {
          System.err.println("Entry \"" + cols[0] + "\" can't be converted to double type!\n");
          continue;
        }
    
        Set<String> v = dsh.get(k);
        if (v == null) {
          dsa.put(k, subset(cols, seq_idx));
          dsh.put(k, v = new HashSet<String>());
        }
    
        v.add(cols[str_idx]);
      }
    }
    
  • sorry, I was not at home often, but now I made this for you

    I know it's too late but just to demonstrate what I meant

    Best, Chrisir ;-)

    // I want to call todos[5] (for example) to get the arraylist saved in that index, containing equal stringlists.
    // https : // forum.processing.org/two/discussion/comment/40340#Comment_40340
    
    
    // declare an array of type ArrayList
    ArrayList[] arrayOfArrayList;
    
    void setup()
    {
      // init
      size(800, 600);
    
      // init the array 
      arrayOfArrayList = new ArrayList[3];
    
      // setting up the ArrayLists within the array 
      for (int i = 0; i < arrayOfArrayList.length; i++) {
        arrayOfArrayList[i] = new ArrayList<String>();
      }
    
      // adding elements to each ArrayList : the number can vary 
      addToArrayList( arrayOfArrayList[0], "Apple", "Strawberry", "Pea");
      addToArrayList( arrayOfArrayList[1], "Pine", "Apple tree");
      addToArrayList( arrayOfArrayList[2], "Cat", "Dog", "mouse", "Elephant");
    
      // print entire array 
      for (int i = 0; i < arrayOfArrayList.length; i++) {
        // print each ArrayList 
        printArrayList (arrayOfArrayList[i] );
      }
    } // func 
    
    void draw() 
    {
      // runs on and on 
      background(0);
    
      // print entire array 
      for (int i = 0; i < arrayOfArrayList.length; i++) {
        // text() each ArrayList 
        textArrayList (arrayOfArrayList[i], i* 29 + 60  );
      }
    } // func 
    
    // --------------------------------------------------
    // Tools 
    
    void printArrayList(ArrayList<String> a1) {
      // print one ArrayList 
      for (String element1 : a1)
        print(element1+" - "); 
      println();
    }
    
    void textArrayList(ArrayList<String> a1, int y) {
      // use text() to display one ArrayList
      int counter=0;
      fill(y*10, y, y*3);  
      for (String element1 : a1) {
        text(element1, counter * 111 + 20, y  );
        counter++;
      }
      println();
    }
    
    void addToArrayList(ArrayList a1, String... list1) {
      // adding elements : the number of elements can vary (they just go into array list1)  
      for (String s1 : list1) 
        a1.add(s1);
    }
    
Sign In or Register to comment.