From: Stefano Crocco Date: 2007-07-12T18:02:58+09:00 Subject: Re: Stripping columns / puts'ing columns Alle gioved狸 12 luglio 2007, Marc Hoeppner ha scritto: > Hi again, > > still on my quest to learn ruby ;) And yet another question - more a > general "how-to-approach" thing, though. > > Let's say I have a text file with a number of rows (it's a molecular > sequence alignment, so each row = one sequence). > I am only interested in those columns in which a certain character > appears - no matter whether in all row or only one. The whole column > should then be puts'ed. > > After thinking about it for a moment, my idea was to store each row in > an array, check each array position for the presence of that particular > character and, if it is, found, to puts this array field [n] and the > corresponding field from all other arrays. Now, there are a couple of > potential problems such as hitting the same column multiple times > because I search multiple arrays... But anyways, since I am rather new > to programming and ruby in particular, that will take me a while - so I > was wondering if there is a more elegant/efficient approach to this, > before I waste my time on this only to find out it doesnt work or could > be done more efficiently (wasted quite some time on another program the > other day only to find out that it can be done with grep...yuck). > > /Marc If I understand your problem correctly, you can try this: max_length = rows.map{|r| r.length}.max cols = rows.map{|r| r.split('') + Array.new(max_length - r.length) }.transpose interesting_cols = cols.select{ |c| c.include?(interesting_character) } Your idea is correct: transform each row from a string to an array of characters. So, youave a nested array, with column elements inside rows. Since you need to select character basing on columns, we need to transpose the outer array. This will leave you with a nested array where each element of the outer array is a column, on which you can use select. The only problem is that to use this approach, your rows need to be of the same length. If they aren't, then you need to add to the array obtained split another array, made of empty strings, whose size is the difference between the length of the longest line and the length of the line. At the end, you may need to remove those elements (you can do this with interesting_cols.each{|c| c.delete('')} ). If all your lines have the same length, then you don't need to do this and the first two lines of my code become cols = rows.map{|r| r.split('')}.transpose I hope this helps Stefano