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