A simple newbie question (arrays and strings)

Discussion in 'Ruby' started by koichirose, May 25, 2008.

  1. koichirose

    koichirose Guest

    Today I started programming in ruby.
    Here's what I managed to do so far:

    string = Dir.entries(".")
    string.delete_at(0)
    string.delete_at(0)

    1. I get a list of files
    2-3. I delete the first two elements ('.' and '..')

    Now my files are all like "something - some other thing"
    I want to split them:

    string.each do |s|
    puts s.split("-")[0]
    end

    So it outputs the "something" part in my filenames.
    Now I'd like to remove duplicate entries (.uniq method right?).
    Can it be done in a single line? If not, how do i get an array
    containing only the "something" part to work on with .uniq?

    I tried with some loops, to create a new array with the splitted string
    in it, but my PHP approach doesn't work:
    i = 0
    for i in string
    splitted = i.split("-")[0]
    i += 1
    end

    Thank you!
     
    koichirose, May 25, 2008
    #1
    1. Advertising

  2. On Sunday 25 May 2008, koichirose wrote:
    > Today I started programming in ruby.
    > Here's what I managed to do so far:
    >
    > string = Dir.entries(".")
    > string.delete_at(0)
    > string.delete_at(0)
    >
    > 1. I get a list of files
    > 2-3. I delete the first two elements ('.' and '..')
    >
    > Now my files are all like "something - some other thing"
    > I want to split them:
    >
    > string.each do |s|
    > puts s.split("-")[0]
    > end
    >
    > So it outputs the "something" part in my filenames.
    > Now I'd like to remove duplicate entries (.uniq method right?).
    > Can it be done in a single line? If not, how do i get an array
    > containing only the "something" part to work on with .uniq?
    >
    > I tried with some loops, to create a new array with the splitted string
    > in it, but my PHP approach doesn't work:
    > i = 0
    > for i in string
    > splitted = i.split("-")[0]
    > i += 1
    > end
    >
    > Thank you!


    If I understand you correctly, this (untested) should do what you want:
    Dir.entries('.')[2..-1].map{|f| f.split('-')[0]}.uniq

    Dir.entries('.')[2..-1]

    returns an array containing all the contents of the current directory except
    the first two entries (actually, the [] method of an array, when called with a
    range returns all the elements of the array from the first index to the last.
    Since negative indexes count from right to left, with the rigthmost element
    having index -1, here you get all the entries from 2 to the last). This avoids
    the two calls to delete_at.

    Then map is called on the array with the names of the files. Array#map passes
    each element of the array to the block and returns an array containing the
    values returned by the block for each element. In this case, each element is a
    string of the form 'something-something_else'. The block splits the name of
    the file on the '-' character, then takes (and implicitly returns) the first
    half (thanks to the [0]). This means that map returns an array containing all
    the first parts of the file names (the ones you want).

    After that, we call uniq on the array, creating a new array without
    duplicates.

    I hope this helps

    Stefano
     
    Stefano Crocco, May 25, 2008
    #2
    1. Advertising

  3. koichirose

    yermej Guest

    On May 25, 3:17 pm, koichirose <> wrote:
    > Today I started programming in ruby.
    > Here's what I managed to do so far:
    >
    > string = Dir.entries(".")
    > string.delete_at(0)
    > string.delete_at(0)
    >
    > 1. I get a list of files
    > 2-3. I delete the first two elements ('.' and '..')
    >
    > Now my files are all like "something - some other thing"
    > I want to split them:
    >
    > string.each do |s|
    > puts s.split("-")[0]
    > end
    >
    > So it outputs the "something" part in my filenames.
    > Now I'd like to remove duplicate entries (.uniq method right?).
    > Can it be done in a single line? If not, how do i get an array
    > containing only the "something" part to work on with .uniq?
    >
    > I tried with some loops, to create a new array with the splitted string
    > in it, but my PHP approach doesn't work:
    > i = 0
    > for i in string
    > splitted = i.split("-")[0]
    > i += 1
    > end
    >
    > Thank you!


    One way would be to use Dir.glob:

    unique_array = Dir.glob('*-*').map {|f| f.split('-')[0]}.uniq

    Then you only get filenames that have - in them.

    Or:

    unique_array = Dir.entries('.')[2..-1].map {|f| f.split('-')[0]}.uniq

    But starting from here:

    > string = Dir.entries(".")
    > string.delete_at(0)
    > string.delete_at(0)

    string.map! {|f| f.split('-')[0]}.uniq!
     
    yermej, May 25, 2008
    #3
  4. koichirose

    koichirose Guest

    Stefano Crocco wrote:
    > If I understand you correctly, this (untested) should do what you want:
    > Dir.entries('.')[2..-1].map{|f| f.split('-')[0]}.uniq


    Hai capito bene :) Continuo in inglese che penso sia contro le regole
    parlare in italiano ^^

    >
    > Dir.entries('.')[2..-1]

    This avoids
    > the two calls to delete_at.


    Nice :)

    > This means that map returns an array containing all
    > the first parts of the file names (the ones you want).


    Does map{} work as some sort of loop in which it executes the split
    method on each element?

    > I hope this helps


    It works! I see that .uniq is case-sensitive (something else !=
    something Else). Can I avoid that?
    Grazie!
     
    koichirose, May 25, 2008
    #4
  5. koichirose

    koichirose Guest

    yermej wrote:
    > unique_array = Dir.entries('.')[2..-1].map {|f| f.split('-')[0]}.uniq
    > string.map! {|f| f.split('-')[0]}.uniq!


    What if I do:
    Dir.entries('.')[2..-1].map! {|f| f.split('-')[0]}.uniq

    with map! instead of map ?
    I'd now have Dir.entries trimmed, splitted and "uniqed" ?
    Thanks
     
    koichirose, May 25, 2008
    #5
  6. * koichirose <> (22:51) schrieb:

    > yermej wrote:
    >> unique_array = Dir.entries('.')[2..-1].map {|f| f.split('-')[0]}.uniq
    >> string.map! {|f| f.split('-')[0]}.uniq!

    >
    > What if I do:
    > Dir.entries('.')[2..-1].map! {|f| f.split('-')[0]}.uniq
    >
    > with map! instead of map ?


    map! changes the array it's called on. since that is a temporary array
    returned by Dir.entries[2..-1] which is discarded after map! that won't
    work.

    mfg, simon .... l
     
    Simon Krahnke, May 26, 2008
    #6
  7. * koichirose <> (22:48) schrieb:

    > It works! I see that .uniq is case-sensitive (something else !=
    > something Else). Can I avoid that?


    Yes, just convert it to lower case before the uniq:

    Dir.entries('.')[2..-1].map{|f| f.split('-')[0].lower}.uniq

    mfg, simon .... l
     
    Simon Krahnke, May 26, 2008
    #7
  8. On Monday 26 May 2008, Simon Krahnke wrote:
    > Dir.entries('.')[2..-1].map{|f| f.split('-')[0].lower}.uniq


    I think you mean downcase, not lower.

    Stefano
     
    Stefano Crocco, May 26, 2008
    #8
  9. koichirose

    koichirose Guest

    Stefano Crocco wrote:
    > I think you mean downcase, not lower.


    Yes, .downcase, confirmed
     
    koichirose, May 26, 2008
    #9
  10. koichirose

    koichirose Guest

    Simon Krahnke wrote:
    > map! changes the array it's called on. since that is a temporary array
    > returned by Dir.entries[2..-1] which is discarded after map! that won't
    > work.


    Right..Thank you!
     
    koichirose, May 26, 2008
    #10
  11. koichirose

    koichirose Guest

    koichirose wrote:
    > Yes, .downcase, confirmed


    I have a problem, why does this work:
    list = Dir.entries('.')[2..-1].map{|f| f.split(' - ')[0].capitalize}

    And this doesn't?
    list2 = Dir.entries('.')[2..-1].map{|f| f.split(' - ')[1].capitalize}

    It returns: hello.rb:7: undefined method `capitalize' for nil:NilClass
    (NoMethodError)
    from hello.rb:7:in `map'

    Thank you
     
    koichirose, May 27, 2008
    #11
  12. koichirose

    Dave Bass Guest

    koichirose wrote:
    > It returns: hello.rb:7: undefined method `capitalize' for nil:NilClass
    > (NoMethodError)


    That error message means you're trying to call the capitalize method on
    something that doesn't exist. I.e. xxx.capitalise where xxx evaluates to
    nil. The class NilClass doesn't have a capitalize method. Your problem
    is with xxx; trying "p"-ing it.





    --
    Posted via http://www.ruby-forum.com/.
     
    Dave Bass, May 27, 2008
    #12
  13. koichirose

    koichirose Guest

    Dave Bass wrote:
    > That error message means you're trying to call the capitalize method on
    > something that doesn't exist. I.e. xxx.capitalise where xxx evaluates to
    > nil. The class NilClass doesn't have a capitalize method. Your problem
    > is with xxx; trying "p"-ing it.
    >



    Ok, but those 2 lines are the same, except that with list2 I take the
    part after ' - '.
    If I do:

    #~ j=0
    #~ for i in list2
    #~ puts list2[j]
    #~ j +=1
    #~ end

    it works. Why are list and list2 behaving differently?
     
    koichirose, May 27, 2008
    #13
  14. koichirose

    Todd Benson Guest

    On Tue, May 27, 2008 at 12:14 PM, koichirose <> wrote:
    > Dave Bass wrote:
    > Ok, but those 2 lines are the same, except that with list2 I take the part
    > after ' - '.
    > If I do:
    >
    > #~ j=0
    > #~ for i in list2
    > #~ puts list2[j]
    > #~ j +=1
    > #~ end


    You have entries that either have no dash "-", or have one but nothing
    after. You can NilClass#puts, but not just any method on it, such as
    #capitalize. If you don't need them (like, for example, counting
    purposes), remove your nils out of the array list with #compact.
    Example in irb...

    [1, nil, 2].compact
    => [1, 2]

    Todd
     
    Todd Benson, May 27, 2008
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Buck Rogers

    a question about arrays and strings

    Buck Rogers, Oct 22, 2003, in forum: C Programming
    Replies:
    6
    Views:
    334
    Micah Cowan
    Oct 22, 2003
  2. Ben

    Strings, Strings and Damned Strings

    Ben, Jun 22, 2006, in forum: C Programming
    Replies:
    14
    Views:
    802
    Malcolm
    Jun 24, 2006
  3. Tarjei Romtveit
    Replies:
    5
    Views:
    335
    Jim Langston
    Aug 22, 2005
  4. Philipp
    Replies:
    21
    Views:
    1,174
    Philipp
    Jan 20, 2009
  5. Pieter Hugo
    Replies:
    13
    Views:
    216
    Robert Klemme
    Nov 26, 2009
Loading...

Share This Page