Skip to content

Instantly share code, notes, and snippets.

@nathany
Created September 21, 2009 19:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nathany/190489 to your computer and use it in GitHub Desktop.
Save nathany/190489 to your computer and use it in GitHub Desktop.
index-of-any, based on Stuart Halloway's Programming Clojure book, but with attempts in Python and Ruby (of course regex would be another, string-only, option)
// Returns the index of the first character contained in searchChars
// From Apache Commons Lang, http://commons.apache.org/lang/
public static int indexOfAny(String str, char[] searchChars) {
if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {
return -1;
}
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
for (int j = 0; j < searchChars.length; j++) {
if (searchChars[j] == ch) {
return i;
}
}
}
return -1;
}
// LOC 14, Branches 4, Exits Method 3, Local Variables 3
;; map collection to vectors with [incrementing number, collection element]
(defn indexed [coll]
(map vector (iterate inc 0) coll))
;; sequence comprehension returns idx when element is in the predicate sequence
;; sets are functions that test membership in the set (pred elt)
(defn index-filter [pred coll]
(when pred
(for [[idx elt] (indexed coll) :when (pred elt)] idx)))
(defn index-of-any [pred coll] (first (index-filter pred coll)))
;; LOC 6, Branches 1, Exits/Method 1, Local Variables 0
;; try it out
(indexed "abcde")
(index-filter #{\a \b} "abcdbbb")
(index-of-any #{\a \b} "zzabyycdxx")
;; generalized, find the index of the 3rd "heads" coin toss
(nth (index-filter #{:h} [:t :t :h :t :h :t :t :t :h :h]) 2)
# Python has indexed() built in, it's called enumerate().
# A list comprehension and slice could do it in one line,
# so long as dealing with Iterable inputs.
def index_filter(predicate, collection): # throws a TypeError if not iterable (i.e. NoneType, int)
return [idx for (idx,elt) in enumerate(collection) if elt in predicate]
def index_of_any(predicate, collection):
return index_filter(predicate, collection)[0] # Warning: NoneType is unsubscriptable
print( index_filter("ab", "sabcdbbb") )
print( index_of_any("ab", "zzabyycdxx") )
# can't iterate over int, so insufficient to only check that not None:
# if predicate != None and collection != None:
# could catch and discard the error
try:
print( index_filter("ab", None) )
except TypeError:
pass
# no :keywords, but still generalized... set {1} works in Python 3 but not 2.x, tuple works
print( "3rd heads:", index_filter((1,), [0, 0, 1, 0, 1, 0, 0, 0, 1, 1])[2] )
# index_of_any turns out to be really easy, thanks to find_index
def index_of_any(predicate, collection)
collection.find_index {|item| predicate.include?(item)}
end
# the gotcha is strings aren't collections directly,
# so we need to call Ruby 1.9's chars() here or in the function (not generic!)
puts index_of_any %w{a b}, "zzabyycdxx".chars
# index_filter was more involved, and needs a temp collection
def index_filter(predicate, collection)
result = []
collection.each_with_index do |item, index|
result << index if predicate.include?(item)
end
result
end
# or it could use an intermediary indexed() method like in the clojure version
def indexed(collection)
result = []
collection.each_with_index {|item, index| result << [item, index] }
result
end
def index_filter_using_indexed(predicate, collection)
indexed(collection).map do |item,index|
index if predicate.include?(item)
end.compact # compact nils away
end
p indexed "abcde".chars
p index_filter %w{a b}, "sabcdbbb".chars
# then index_of_any just becomes a call to first() or a slice like Python
puts index_filter(%w{a b}, "zzabyycdxx".chars).first
# yup, generic, except the whole chars() thing
print "3rd heads:"
puts index_filter([:h], [:t, :t, :h, :t, :h, :t, :t, :t, :h, :h])[2]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment