pub fn attribute_count<T, K: PartialEq>(
elements: impl IntoIterator<Item = T>,
attribute: impl Fn(T) -> Option<K>,
) -> Vec<(K, usize)>Expand description
How often each value of some property of a stream’s elements comes, in
the order each value is first met: music21’s attributeCount, with the
property a function of the element rather than the name of one, and
None where the element has no such property – which is music21’s
hasattr test.
The elements are whatever reading the caller counts over: a stream’s own
events, a recursive one
(recurse, leaves),
or either of those filtered, as music21 takes a stream or a stream
iterator.
The counts are in counting order, as Python’s Counter keeps them, so
most_common is a sort by count that leaves ties as they stand.
use music21_rs::analysis::elements::attribute_count;
use music21_rs::stream::StreamElement;
use music21_rs::tinynotation::from_tiny_notation;
let line = from_tiny_notation("4/4 c4 d8 e8 f2")?;
let lengths = attribute_count(line.recurse(), |(_, element)| match element {
StreamElement::Note(_) => Some(element.quarter_length()),
// A clef or a meter is not a note, and is not counted -- as
// music21 passes over an element the attribute is not on.
_ => None,
});
assert_eq!(lengths, [(1.0, 1), (0.5, 2), (2.0, 1)]);