special Array method about Unix pathes

U

Une Bévue

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 ?
 
C

Charles D Hixson

Une said:
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?
 
S

Sebastian Hungerecker

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

HTH,
Sebastian
=2D-=20
NP: Iron Maiden - Infinite Dreams
Jabber: (e-mail address removed)
ICQ: 205544826
 
U

Une Bévue

Charles D Hixson said:
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!
 
S

Stefano Crocco

Alle mercoled=EC 19 settembre 2007, Une B=E9vue ha scritto:
here is the goal:

i've an Array of Unix pathes :
forbidden =3D ["/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" =AB belongs =BB
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 =3D ["/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) =3D=3D=3D 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 =3D arg.dup.sort_by{|i| i.size} =20
a.inject([]) do |res, i| =20
res.any?{|j| i.index(j) =3D=3D 0 } ? res : (res << i)=20
end
end

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

Regarding your code, I'd say names are correct, as far as English is=20
concerned. I'd like to give you a copule of suggestions:
* use underscores instead of camel-case (include_path? instead of includePa=
th,=20
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, th=
ere=20
are several cases in which both methods exist, with the ones ending in s be=
ing=20
obsolete (for example, File.exists? and File.exist?) For consistency, I thi=
nk=20
it's better to follow the same convention.

Stefano
 
N

Nobuyoshi Nakada

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.
 
R

Robert Klemme

2007/9/19 said:
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=E9vue, 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
 
U

Une Bévue

Robert Klemme said:
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!"...
 
U

Une Bévue

Stefano Crocco said:
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 !
 
S

Stefano Crocco

Alle mercoled=EC 19 settembre 2007, Une B=E9vue ha scritto:
=A0 forbiddenList:
=A0 - /Volumes/EMTEC KEY/emtec_dl
=A0 - /Volumes/EMTEC KEY/emtec_dl/v233r001/Setup.exe
=A0 - /Volumes/U3 System
=A0 - /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 =3D arg.dup.sort_by{|i| i.size}
irb: 003+> a.inject([]) do |res, i|
irb: 004*> res.any?{|j| i[0, j.size] =3D=3D j} ? res : (res << i)
irb: 005+> end
irb: 006+> end
nil
irb: 007> forbidden =3D ["/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=20
KEY/emtec_dl/v233r001/Setup.exe", "/Volumes/U3 System", "/Volumes/U3=20
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
 
U

Une Bévue

Une Bévue said:
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

sorry, in fact that works wheb used as :


forbidden = [
"/Volumes/U3 System",
"/Volumes/EMTEC KEY/emtec_dl",
"/Volumes/EMTEC KEY/emtec_dl/Win98SE new driver.exe",
"/Volumes/EMTEC KEY/emtec_dl/v233r001/Setup.exe",
"/Volumes/EMTEC KEY/emtec_dl/v233r001",
"/Volumes/U3 System/LaunchU3.exe",
"/Volumes/U3 System/Launchpad.zip"
]

p forbidden
forbidden = select_toplevel_paths( forbidden )
p forbidden


but not when used in a class :

class SyncDataSource < OSX::NSObject

def initialize

[...]

@forbiddenList = [ ]

[...]

end

[...]

def addForbidden( notification )

[...]

p @forbiddenList
@forbiddenList = select_toplevel_paths( @forbiddenList )
p @forbiddenList

[...]

end

end

i don't understand why for the time being...
 
R

Robert Klemme

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

If it's sorted anyway that's probably the approach I'd take.
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.

I am not sure what you mean here. You have to build the tree first
before you can decide which branches you can omit. With "output" I did
not necessarily mean output to screen, but rather output from the
method. Maybe I should have chosen a different wording. I am sorry if
that caused confusion.
Yes i've corrected that, it's an habit coming from java, as the getter
"getContainers!"...

Different languages, different conventions. :)

Kind regards

robert
 
U

Une Bévue

Robert Klemme said:
I am not sure what you mean here. You have to build the tree first
before you can decide which branches you can omit. With "output" I did
not necessarily mean output to screen, but rather output from the
method. Maybe I should have chosen a different wording. I am sorry if
that caused confusion.


i've found a simpler approach, in fact, this list of pathes is entered
by the user using a File/folder chooser window, then instead of walking
a three or something else, xhen the user enter a new path right now i
check only if this path is allready taken into account by :

files.each { |f|
f_to_s = f.to_s
@forbiddenList << f_to_s unless @forbiddenList.include_path?( f_to_s )
}

with :
files the File(s)/Folder(s) entered by the user ;
f.to_s converting NSString to Ruby String (NS stands for NextStep) ;
Array#include_path?( a_path ) being :
class Array
def include_path?(path)
self.any? { | x | a_path.rindex( x, 0 ) }
end
end

the only thing i dislike is in that pathes have nothing to do with
Array,i must rexrite this part.
Different languages, different conventions. :)

yes right, here i'm embarassed because my code isn't "pure" Ruby, it's
RubyCocoa (a bridge between Cocoa/ObjC on Mac OS X) and in RubyCocoa the
Cocoa methods like :

NSOpenPanel#beginSheetForDirectory:file:types:modalForWindow:modalDelega
te:didEndSelector:contextInfo:

are translated, on the Ruby side, in :

beginSheetForDirectory_file_types_modalForWindow_modalDelegate_didEndSel
ector:contextInfo( ... )

then "_" replaces ":" and still camelized...
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,264
Messages
2,571,323
Members
48,007
Latest member
Elvis60357

Latest Threads

Top