public
Last active

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)

  • Download Gist
gistfile1.java
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// 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
gistfile2.clj
Clojure
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
;; 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)
gistfile3.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
# 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] )
gistfile4.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
# 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]

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.