NAME
Sidef::Types::Set::Bag - A multiset (bag) data structure for Sidef
DESCRIPTION
This class implements a multiset (also known as a bag), which is a collection that allows duplicate elements and tracks the frequency of each unique element. Unlike a regular Set where each element appears at most once, a Bag maintains a count for each element, making it useful for frequency analysis and operations that need to preserve multiplicity.
A Bag is essentially a mapping from elements to their frequencies, where the frequency represents how many times each element appears in the collection.
SYNOPSIS
var a = Bag(1, 1, 2, 3)
var b = Bag(1, 4, 3, 5)
say (a | b) #=> Bag(1, 1, 2, 3, 4, 5)
say (a ^ b) #=> Bag(1, 2, 4, 5)
say (a & b) #=> Bag(1, 3)
say (a - b) #=> Bag(1, 2)
say (a + b) #=> Bag(1, 1, 1, 2, 3, 3, 4, 5)
say a.count(1) #=> 2
say a.elems #=> 3
say a.len #=> 4
say a.keys #=> [1, 2, 3]
say a.freq #=> [[1, 2], [2, 1], [3, 1]]
INHERITS
Inherits methods from:
* Sidef::Types::Set::Set
METHODS
&
a & b
Returns the intersection of two bags. The resulting bag contains elements that appear in both bags, with the frequency being the minimum of the frequencies in the two bags.
Example:
Bag(1, 1, 2, 3) & Bag(1, 2, 2, 4) #=> Bag(1, 2)
Aliases: ∩, and, intersection
+
a + b
Returns the sum (concatenation) of two bags. The resulting bag contains all elements from both bags, with frequencies added together.
Example:
Bag(1, 2) + Bag(2, 3) #=> Bag(1, 2, 2, 3)
Aliases: concat
-
a - b
Returns the difference of two bags. The resulting bag contains elements from the first bag with their frequencies reduced by the frequencies in the second bag. Elements are removed entirely if their frequency becomes zero or negative.
Example:
Bag(1, 1, 2, 3) - Bag(1, 3) #=> Bag(1, 2)
Aliases: ∖, sub, diff, difference
...
a ... b
Returns an array containing all elements from the bag expanded according to their frequencies, up to the range specified.
Aliases: to_list
<<
a << b
Adds an element to the bag, incrementing its frequency by 1. Returns the modified bag.
Example:
var bag = Bag(1, 2)
bag << 2 #=> Bag(1, 2, 2)
Aliases: add, push, append
^
a ^ b
Returns the symmetric difference of two bags. The resulting bag contains elements that appear in either bag but not in both (with equal frequency). Frequencies are calculated as the absolute difference.
Example:
Bag(1, 1, 2) ^ Bag(1, 3) #=> Bag(1, 2, 3)
Aliases: xor, symdiff, symmetric_difference
|
a | b
Returns the union of two bags. The resulting bag contains all elements from both bags, with the frequency being the maximum of the frequencies in the two bags.
Example:
Bag(1, 1, 2) | Bag(1, 3, 3) #=> Bag(1, 1, 2, 3, 3)
Aliases: ∪, or, union
∋
a ∋ b
Returns true if the bag contains the specified element (at least once), false otherwise.
Example:
Bag(1, 2, 3) ∋ 2 #=> true
Bag(1, 2, 3) ∋ 5 #=> false
Aliases: has, exists, has_key, haskey, contain, include, contains, includes
∌
a ∌ b
Returns true if the bag does not contain the specified element, false otherwise. This is the negation of the ∋ operator.
Example:
Bag(1, 2, 3) ∌ 5 #=> true
Bag(1, 2, 3) ∌ 2 #=> false
≠
a ≠ b
Returns true if two bags are not equal (contain different elements or different frequencies), false otherwise.
Example:
Bag(1, 2) ≠ Bag(1, 2, 2) #=> true
Aliases: !=, ne
≡
a ≡ b
Returns true if two bags are equal (contain the same elements with the same frequencies), false otherwise.
Example:
Bag(1, 2, 2) ≡ Bag(2, 1, 2) #=> true
Aliases: ==, eq
≤
a ≤ b
Returns true if bag 'a' is a subset of bag 'b' (every element in 'a' appears in 'b' with at least the same frequency), false otherwise.
Example:
Bag(1, 2) ≤ Bag(1, 2, 2, 3) #=> true
Aliases: ⊆, <=, is_subset
≥
a ≥ b
Returns true if bag 'a' is a superset of bag 'b' (every element in 'b' appears in 'a' with at least the same frequency), false otherwise.
Example:
Bag(1, 2, 2, 3) ≥ Bag(1, 2) #=> true
Aliases: ⊇, >=, is_superset
add_kv
self.add_kv(obj, n)
Adds an element to the bag with a specific frequency increment. Increases the frequency of 'obj' by 'n'. Returns the modified bag.
Example:
var bag = Bag(1, 2)
bag.add_kv(2, 3) #=> Bag(1, 2, 2, 2, 2)
Aliases: push_kv, add_pair, append_kv, push_pair, append_pair
add_kvs
self.add_kvs(*pairs)
Adds multiple elements with their frequencies to the bag. Accepts pairs of [element, frequency] as arguments. Returns the modified bag.
Example:
var bag = Bag(1)
bag.add_kvs([2, 3], [3, 2]) #=> Bag(1, 2, 2, 2, 3, 3)
Aliases: push_kvs, add_pairs, append_kvs, push_pairs, append_pairs
clone
self.clone
Returns a shallow copy of the bag with the same elements and frequencies.
Example:
var a = Bag(1, 2, 3)
var b = a.clone
b << 4
say a #=> Bag(1, 2, 3)
say b #=> Bag(1, 2, 3, 4)
collect
self.collect(block)
Applies a transformation block to each element in the bag (respecting multiplicity) and returns a new bag with the transformed elements.
Example:
Bag(1, 2, 2).collect { _ * 2 } #=> Bag(2, 4, 4)
contains_all
self.contains_all(*objects)
Returns true if the bag contains all of the specified objects (at least once each), false otherwise.
Example:
Bag(1, 2, 3, 3).contains_all(1, 3) #=> true
Bag(1, 2, 3).contains_all(1, 4) #=> false
count_by
self.count_by(block)
Groups elements by the result of applying the block to each element (respecting multiplicity) and returns a new bag where keys are the block results and frequencies are the counts.
Example:
Bag(1, 2, 3, 4).count_by { _ % 2 } #=> Bag(0, 0, 1, 1)
delete
self.delete(*objects)
Removes one occurrence of each specified object from the bag. Decrements the frequency by 1 for each object. Returns the modified bag.
Example:
Bag(1, 1, 2, 3).delete(1, 2) #=> Bag(1, 3)
Aliases: remove, discard
delete_all
self.delete_all(*objects)
Removes all occurrences of each specified object from the bag. Returns the modified bag.
Example:
Bag(1, 1, 2, 3).delete_all(1, 2) #=> Bag(3)
Aliases: remove_all, discard_all
delete_first_if
self.delete_first_if(block)
Removes the first element (according to iteration order) that satisfies the condition in the block. Decrements its frequency by 1. Returns the modified bag.
Example:
Bag(1, 2, 3, 4).delete_first_if { _ > 2 } #=> Bag(1, 2, 4)
delete_if
self.delete_if(block)
Removes all elements that satisfy the condition in the block. Removes all occurrences of matching elements. Returns the modified bag.
Example:
Bag(1, 2, 2, 3, 4).delete_if { _ % 2 == 0 } #=> Bag(1, 3)
delete_key
self.delete_key(obj)
Completely removes the specified key (element) from the bag along with all its occurrences. Returns the modified bag.
Example:
Bag(1, 1, 2, 3).delete_key(1) #=> Bag(2, 3)
Aliases: remove_key, discard_key
dump
self.dump
Returns a string representation of the bag suitable for debugging or serialization, showing the internal structure.
Example:
Bag(1, 2, 2).dump #=> "Bag(1, 2, 2)"
each
self.each(block)
Iterates over each element in the bag (respecting multiplicity) and executes the block for each occurrence. Returns the bag.
Example:
Bag(1, 2, 2).each { say _ }
# Prints: 1, 2, 2
each_2d
self.each_2d(block)
Iterates over the bag as a 2D structure, passing pairs of [element, frequency] to the block. Returns the bag.
Example:
Bag(1, 2, 2).each_2d { |k, v| say "#{k}: #{v}" }
# Prints: 1: 1, 2: 2
each_kv
self.each_kv(block)
Iterates over key-value pairs in the bag, passing the element and its frequency to the block. Returns the bag.
Example:
Bag(1, 2, 2, 3).each_kv { |k, v| say "#{k} appears #{v} times" }
elems
self.elems
Returns the number of unique elements (distinct keys) in the bag.
Example:
Bag(1, 1, 2, 3).elems #=> 3
Aliases: keys_len
freq
self.freq
Returns an array of [element, frequency] pairs for all elements in the bag.
Example:
Bag(1, 1, 2, 3).freq #=> [[1, 2], [2, 1], [3, 1]]
get
self.get(obj)
Returns the frequency (count) of the specified element in the bag. Returns 0 if the element is not present.
Example:
Bag(1, 1, 2, 3).get(1) #=> 2
Bag(1, 1, 2, 3).get(5) #=> 0
Aliases: count
grep
self.grep(block)
Returns a new bag containing only the elements (with their frequencies) that satisfy the condition in the block.
Example:
Bag(1, 2, 2, 3, 4).grep { _ % 2 == 0 } #=> Bag(2, 2, 4)
Aliases: select
grep_2d
self.grep_2d(block)
Filters the bag by applying the block to [element, frequency] pairs. Returns a new bag with pairs that satisfy the condition.
Example:
Bag(1, 2, 2, 3).grep_2d { |k, v| v > 1 } #=> Bag(2, 2)
grep_kv
self.grep_kv(block)
Filters the bag by applying the block to element-frequency pairs. Returns a new bag with elements whose key-value pairs satisfy the condition.
Example:
Bag(1, 2, 2, 3, 3, 3).grep_kv { |k, v| k == v } #=> Bag(3, 3, 3)
iter
self.iter
Returns an iterator object that can be used to iterate over the elements in the bag (respecting multiplicity).
Example:
var iter = Bag(1, 2, 2).iter
say iter.next #=> 1
say iter.next #=> 2
say iter.next #=> 2
join
self.join(*rest)
Converts the bag elements to strings and joins them using the specified separator. Multiple arguments are treated as additional separators for nested structures.
Example:
Bag(1, 2, 2, 3).join(", ") #=> "1, 2, 2, 3"
keys
self.keys
Returns an array of unique elements (keys) in the bag, without their frequencies.
Example:
Bag(1, 1, 2, 3).keys #=> [1, 2, 3]
kv
self.kv
Returns an array of [element, frequency] pairs for all elements in the bag. Similar to freq().
Example:
Bag(1, 1, 2).kv #=> [[1, 2], [2, 1]]
Aliases: pairs
len
self.len
Returns the total number of elements in the bag, counting multiplicities (sum of all frequencies).
Example:
Bag(1, 1, 2, 3).len #=> 4
Aliases: size, length
map
self.map(block)
Applies the block to each element in the bag (respecting multiplicity) and returns a new bag with the results.
Example:
Bag(1, 2, 2).map { _ * 2 } #=> Bag(2, 4, 4)
map_2d
self.map_2d(block)
Applies the block to [element, frequency] pairs and returns a new bag constructed from the results.
Example:
Bag(1, 2, 2).map_2d { |k, v| [k * 2, v] } #=> Bag(2, 4, 4)
map_kv
self.map_kv(block)
Applies the block to element-frequency pairs and returns a new bag constructed from the results.
Example:
Bag(1, 2).map_kv { |k, v| [k + 1, v * 2] } #=> Bag(2, 2, 3, 3)
max
self.max
Returns the maximum element in the bag (ignoring frequencies).
Example:
Bag(1, 5, 3, 3).max #=> 5
max_by
self.max_by(block)
Returns the element for which the block returns the maximum value (ignoring frequencies).
Example:
Bag(1, 2, 3).max_by { _ * -1 } #=> 1
min
self.min
Returns the minimum element in the bag (ignoring frequencies).
Example:
Bag(5, 1, 3, 3).min #=> 1
min_by
self.min_by(block)
Returns the element for which the block returns the minimum value (ignoring frequencies).
Example:
Bag(1, 2, 3).min_by { _ * -1 } #=> 3
new
self.new
Creates a new empty bag, or a bag initialized with the provided elements.
Example:
var bag = Bag.new
var bag2 = Bag.new(1, 2, 2, 3) #=> Bag(1, 2, 2, 3)
Aliases: call
pop
self.pop
Removes and returns an arbitrary element from the bag. Decrements its frequency by 1. The bag must not be empty.
Example:
var bag = Bag(1, 2, 2)
bag.pop #=> returns one element, e.g., 1
set_kv
self.set_kv(obj, n)
Sets the frequency of an element to a specific value. If n is 0 or negative, the element is removed. Returns the modified bag.
Example:
var bag = Bag(1, 2, 2)
bag.set_kv(2, 5) #=> Bag(1, 2, 2, 2, 2, 2)
Aliases: update_kv, update_pair, replace_pair
set_kvs
self.set_kvs(*pairs)
Sets the frequencies of multiple elements. Accepts pairs of [element, frequency]. Returns the modified bag.
Example:
var bag = Bag(1)
bag.set_kvs([1, 3], [2, 2]) #=> Bag(1, 1, 1, 2, 2)
Aliases: update_kvs, update_pairs, replace_pairs
shift
self.shift
Removes and returns an arbitrary element from the bag (typically the first in iteration order). Decrements its frequency by 1. The bag must not be empty.
Example:
var bag = Bag(1, 2, 2)
bag.shift #=> returns one element, e.g., 1
sort
self.sort(block)
Returns an array of elements sorted according to the optional comparison block. Elements are expanded according to their frequencies.
Example:
Bag(3, 1, 2, 2).sort #=> [1, 2, 2, 3]
Bag(3, 1, 2).sort { |a, b| b <=> a } #=> [3, 2, 1]
sort_by
self.sort_by(block)
Returns an array of elements sorted by the result of applying the block to each element. Elements are expanded according to their frequencies.
Example:
Bag(1, 2, 3, 3).sort_by { _ * -1 } #=> [3, 3, 2, 1]
to_a
self.to_a
Converts the bag to an array, expanding all elements according to their frequencies.
Example:
Bag(1, 2, 2, 3).to_a #=> [1, 2, 2, 3]
Aliases: expand, to_array
to_bag
self.to_bag
Returns the bag itself (identity operation).
Example:
var bag = Bag(1, 2, 3)
bag.to_bag #=> Bag(1, 2, 3)
top
self.top(n)
Returns an array of the top n most common elements with their frequencies, as [element, frequency] pairs, sorted by frequency in descending order.
Example:
Bag(1, 2, 2, 3, 3, 3).top(2) #=> [[3, 3], [2, 2]]
Aliases: most_common
to_set
self.to_set
Converts the bag to a set, discarding frequency information and keeping only unique elements.
Example:
Bag(1, 1, 2, 3).to_set #=> Set(1, 2, 3)
uniq
self.uniq
Returns a new bag with all elements having a frequency of 1 (effectively converting it to behave like a set while maintaining bag type).
Example:
Bag(1, 1, 2, 3, 3).uniq #=> Bag(1, 2, 3)
Aliases: unique
values
self.values
Returns an array of all frequency values in the bag.
Example:
Bag(1, 1, 2, 3).values #=> [2, 1, 1]
SEE ALSO
AUTHOR
Daniel "Trizen" Șuteu
LICENSE
This library is free software; you can redistribute it and/or modify it under the same terms as Sidef itself.