lib/abstractivator/enumerable_ext.rb in abstractivator-0.8.0 vs lib/abstractivator/enumerable_ext.rb in abstractivator-0.10.0

- old
+ new

@@ -100,6 +100,52 @@ primary = compare.call(a, b) primary != 0 ? primary : (ai <=> bi) end sorted.map(&:first) end + + def select_map(&block) + self.map(&block).select { |x| x } + end + + def single + if size != 1 + raise ArgumentError, "expected a single element but was: #{inspect}" + end + self.first + end + + def unique_by(&block) + self.group_by(&block).map { |_, vs| vs.first } + end + + def duplicates(&block) + group_by(&block) + .select { |_, vs| vs.size > 1 } + .map { |k, _| k } + end + + # Folds over a cyclic graph. 'self' is the root node set. + # Each node is visited once, in an unspecified order. + # Node identity is determined by #object_id + # @param init [Object] the initial accumulator + # @param get_children_proc [Proc] takes a node and returns its children (or neighbors) + # @yieldparam acc [Object] the accumulator + # @yieldparam node [Object] the current node + # @yieldreturn [Object] the accumulator, after visiting all nodes once + def cyclic_fold(init, get_children_proc, &block) + xs = self.dup + seen = Set.new + acc = init + while xs.any? + x = xs.shift + if seen.include?(x.object_id) + next + else + seen.add(x.object_id) + acc = block.call(acc, x) + xs.concat(get_children_proc.call(x)) + end + end + acc + end end