[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

special Array method about Unix pathes

unbewusst.sein

9/19/2007 3:59:00 PM


here is the goal:

i've an Array of Unix pathes :
forbidden = ["/Volumes/U3 System",
"/Volumes/EMTEC KEY/emtec_dl",
"/Volumes/EMTEC KEY/emtec_dl/Win98SE new driver.exe",
"/Volumes/EMTEC KEY/emtec_dl/v233r001"
]

i want to forbid access to those pathes BUT since, for example,
"/Volumes/EMTEC KEY/emtec_dl/Win98SE new driver.exe" « belongs »
to the path (it's below this path) "/Volumes/EMTEC KEY/emtec_dl"
it is unusefull to have it in the Array.

in the case above i'd like to return :

forbidden = ["/Volumes/U3 System",
"/Volumes/EMTEC KEY/emtec_dl"
]

what i've done :


class Array
def includePath?(path)
self.each { | x |
return true if path.startsWith?(x)
}
return false
end
def getContainers!
self.delete_if { | x | ( self - [ x ] ).includePath?( x ) }
end
end

class String
def startsWith?(dir)
self.index(dir) === 0
end
end

then forbidden.getContainers! gives me the expected result.

what do you think about this solution ?
could you propose a better one ?

also, because english isn't my mother tongue, are my methods naming
correct ?

--
Une Bévue
13 Answers

Charles Hixson

9/19/2007 4:32:00 PM

0

Une Bévue wrote:
> here is the goal:
>
> i've an Array of Unix pathes :
> forbidden = ["/Volumes/U3 System",
> "/Volumes/EMTEC KEY/emtec_dl",
> "/Volumes/EMTEC KEY/emtec_dl/Win98SE new driver.exe",
> "/Volumes/EMTEC KEY/emtec_dl/v233r001"
> ]
>
> i want to forbid access to those pathes BUT since, for example,
> "/Volumes/EMTEC KEY/emtec_dl/Win98SE new driver.exe" « belongs »
> to the path (it's below this path) "/Volumes/EMTEC KEY/emtec_dl"
> it is unusefull to have it in the Array.
>
> in the case above i'd like to return :
>
> forbidden = ["/Volumes/U3 System",
> "/Volumes/EMTEC KEY/emtec_dl"
> ]
>
> what i've done :
>
>
> class Array
> def includePath?(path)
> self.each { | x |
> return true if path.startsWith?(x)
> }
> return false
> end
> def getContainers!
> self.delete_if { | x | ( self - [ x ] ).includePath?( x ) }
> end
> end
>
> class String
> def startsWith?(dir)
> self.index(dir) === 0
> end
> end
>
> then forbidden.getContainers! gives me the expected result.
>
> what do you think about this solution ?
> could you propose a better one ?
>
> also, because english isn't my mother tongue, are my methods naming
> correct ?
>
>
Array doesn't seem the proper class to have a includePath? method,
otherwise the names look reasonable. If the method is in Array, then a
reasonable name might be includesStart?

Sebastian Hungerecker

9/19/2007 4:38:00 PM

0

Charles D Hixson wrote:
> >      self.each { | x |
> >        return true if path.startsWith?(x)
> >      }
> >      return false

self.any? {|x| path.starts_with?(x) }

HTH,
Sebastian
--
NP: Iron Maiden - Infinite Dreams
Jabber: sepp2k@jabber.org
ICQ: 205544826

unbewusst.sein

9/19/2007 5:04:00 PM

0

Sebastian Hungerecker <sepp2k@googlemail.com> wrote:

> self.any? {|x| path.starts_with?(x) }

fine thanks, i didn't know the #any?
--
Une Bévue

unbewusst.sein

9/19/2007 5:04:00 PM

0

Charles D Hixson <charleshixsn@earthlink.net> wrote:

> Array doesn't seem the proper class to have a includePath? method,
> otherwise the names look reasonable.

i'll lokk if there is something more related to Unix pathes...

> If the method is in Array, then a
> reasonable name might be includesStart?

OK, thanks!


--
Une Bévue

Stefano Crocco

9/19/2007 6:25:00 PM

0

Alle mercoledì 19 settembre 2007, Une Bévue ha scritto:
> here is the goal:
>
> i've an Array of Unix pathes :
> forbidden = ["/Volumes/U3 System",
> "/Volumes/EMTEC KEY/emtec_dl",
> "/Volumes/EMTEC KEY/emtec_dl/Win98SE new driver.exe",
> "/Volumes/EMTEC KEY/emtec_dl/v233r001"
> ]
>
> i want to forbid access to those pathes BUT since, for example,
> "/Volumes/EMTEC KEY/emtec_dl/Win98SE new driver.exe" « belongs »
> to the path (it's below this path) "/Volumes/EMTEC KEY/emtec_dl"
> it is unusefull to have it in the Array.
>
> in the case above i'd like to return :
>
> forbidden = ["/Volumes/U3 System",
> "/Volumes/EMTEC KEY/emtec_dl"
> ]
>
> what i've done :
>
>
> class Array
> def includePath?(path)
> self.each { | x |
> return true if path.startsWith?(x)
> }
> return false
> end
> def getContainers!
> self.delete_if { | x | ( self - [ x ] ).includePath?( x ) }
> end
> end
>
> class String
> def startsWith?(dir)
> self.index(dir) === 0
> end
> end
>
> then forbidden.getContainers! gives me the expected result.
>
> what do you think about this solution ?
> could you propose a better one ?
>
> also, because english isn't my mother tongue, are my methods naming
> correct ?

This is my alternative solution:

def select_toplevel_paths arg
a = arg.dup.sort_by{|i| i.size}
a.inject([]) do |res, i|
res.any?{|j| i.index(j) == 0 } ? res : (res << i)
end
end

It doesn't change the contents of the array and it's not a method of class
Array, because, in my opinion, it's a too specialized method to be put in a
core class.

Regarding your code, I'd say names are correct, as far as English is
concerned. I'd like to give you a copule of suggestions:
* use underscores instead of camel-case (include_path? instead of includePath,
for example), because it's the more common style in the ruby community
* use start_with? instead of starts_with?. In the ruby standard library, there
are several cases in which both methods exist, with the ones ending in s being
obsolete (for example, File.exists? and File.exist?) For consistency, I think
it's better to follow the same convention.

Stefano

Nobuyoshi Nakada

9/19/2007 6:43:00 PM

0

Hi,

At Thu, 20 Sep 2007 03:24:58 +0900,
Stefano Crocco wrote in [ruby-talk:269890]:
> def select_toplevel_paths arg
> a = arg.dup.sort_by{|i| i.size}
> a.inject([]) do |res, i|
> res.any?{|j| i.index(j) == 0 } ? res : (res << i)

i.rindex(j, 0) is faster than i.index(j) == 0 when j matches in
the middle.

> * use start_with? instead of starts_with?. In the ruby standard library, there
> are several cases in which both methods exist, with the ones ending in s being
> obsolete (for example, File.exists? and File.exist?) For consistency, I think
> it's better to follow the same convention.

And ruby 1.9 has String#start_with? already in fact.

--
Nobu Nakada

Robert Klemme

9/19/2007 6:46:00 PM

0

2007/9/19, Sebastian Hungerecker <sepp2k@googlemail.com>:
> Charles D Hixson wrote:
> > > self.each { | x |
> > > return true if path.startsWith?(x)
> > > }
> > > return false
>
> self.any? {|x| path.starts_with?(x) }

You can even leave the "self." out. :-)

I can think of several approaches to solve this:

1. order the array and do a second iteration where each item is
checked against the last seen prefix; the idea is that every string
comes before the strings that contain it as prefix.

2. insert names into a tree and output only prefixes during a tree walk.

Bévue, the only issue I see with your method naming is that in Ruby
methods typically use under_scores and not CamelCase as in Java.

Kind regards

robert

unbewusst.sein

9/19/2007 7:26:00 PM

0

Robert Klemme <shortcutter@googlemail.com> wrote:

>
> You can even leave the "self." out. :-)

OK !

> I can think of several approaches to solve this:
>
> 1. order the array and do a second iteration where each item is
> checked against the last seen prefix; the idea is that every string
> comes before the strings that contain it as prefix.

fine, the Array is allready ordered elsewhere, i thought putting sort!
in this method ))

> 2. insert names into a tree and output only prefixes during a tree walk.

ok, i see what you mean, may be better not to do that when output rather
than when building the three having a means to compare three deepness.

> Bévue, the only issue I see with your method naming is that in Ruby
> methods typically use under_scores and not CamelCase as in Java.

Yes i've corrected that, it's an habit coming from java, as the getter
"getContainers!"...
--
Une Bévue

unbewusst.sein

9/19/2007 7:26:00 PM

0

Stefano Crocco <stefano.crocco@alice.it> wrote:

>
> This is my alternative solution:
>
> def select_toplevel_paths arg
> a = arg.dup.sort_by{|i| i.size}
> a.inject([]) do |res, i|
> res.any?{|j| i.index(j) == 0 } ? res : (res << i)
> end
> end

clever solution, thanks a lot !

however with the following (part of a yaml file) :

forbiddenList:
- /Volumes/EMTEC KEY/emtec_dl
- /Volumes/EMTEC KEY/emtec_dl/v233r001/Setup.exe
- /Volumes/U3 System
- /Volumes/U3 System/Launchpad.zip

your select_toplevel_paths don't remove /Volumes/EMTEC
KEY/emtec_dl/v233r001/Setup.exe and /Volumes/U3 System/Launchpad.zip

>
> It doesn't change the contents of the array and it's not a method of class
> Array, because, in my opinion, it's a too specialized method to be put in a
> core class.

U're right, i was embarassed with that point.

> Regarding your code, I'd say names are correct, as far as English is
> concerned. I'd like to give you a copule of suggestions:
> * use underscores instead of camel-case (include_path? instead of includePath,
> for example), because it's the more common style in the ruby community
> * use start_with? instead of starts_with?. In the ruby standard library, there
> are several cases in which both methods exist, with the ones ending in s being
> obsolete (for example, File.exists? and File.exist?) For consistency, I think
> it's better to follow the same convention.

OK, done !

--
Une Bévue

Stefano Crocco

9/19/2007 7:43:00 PM

0

Alle mercoledì 19 settembre 2007, Une Bévue ha scritto:
>   forbiddenList:
>   - /Volumes/EMTEC KEY/emtec_dl
>   - /Volumes/EMTEC KEY/emtec_dl/v233r001/Setup.exe
>   - /Volumes/U3 System
>   - /Volumes/U3 System/Launchpad.zip
>
> your select_toplevel_paths don't remove /Volumes/EMTEC
> KEY/emtec_dl/v233r001/Setup.exe and /Volumes/U3 System/Launchpad.zip

It works for me:

irb: 001> def select_toplevel_path arg
irb: 002+> a = arg.dup.sort_by{|i| i.size}
irb: 003+> a.inject([]) do |res, i|
irb: 004*> res.any?{|j| i[0, j.size] == j} ? res : (res << i)
irb: 005+> end
irb: 006+> end
nil
irb: 007> forbidden = ["/Volumes/EMTEC KEY/emtec_dl",
irb: 008*> "/Volumes/EMTEC KEY/emtec_dl/v233r001/Setup.exe",
irb: 009*> "/Volumes/U3 System",
irb: 010*> "/Volumes/U3 System/Launchpad.zip"
irb: 011+> ]
["/Volumes/EMTEC KEY/emtec_dl", "/Volumes/EMTEC
KEY/emtec_dl/v233r001/Setup.exe", "/Volumes/U3 System", "/Volumes/U3
System/Launchpad.zip"]
irb: 012> select_toplevel_path forbidden
["/Volumes/U3 System", "/Volumes/EMTEC KEY/emtec_dl"]

Notice that this doesn't change the forbidden array, but creates a new one.

Stefano