///|
/// Copy a corpus while retaining only documents with ids in a half-open range.
pub fn slice_documents(
docs : Array[Document],
start : Int,
end : Int,
) -> Array[Document] {
let first = if start < 0 { 0 } else { start }
let last = if end < first {
first
} else if end > docs.length() {
docs.length()
} else {
end
}
let result = []
for i = first; i < last; i = i + 1 {
result.push(docs[i])
}
result
}
///|
/// Split a corpus into a deterministic prefix and suffix.
pub fn split_documents(
docs : Array[Document],
prefix_count : Int,
) -> (Array[Document], Array[Document]) {
let prefix = if prefix_count < 0 {
0
} else if prefix_count > docs.length() {
docs.length()
} else {
prefix_count
}
(
slice_documents(docs, 0, prefix),
slice_documents(docs, prefix, docs.length()),
)
}
///|
/// Return documents whose ids start with a prefix.
pub fn filter_id_prefix(
docs : Array[Document],
prefix : String,
) -> Array[Document] {
let result = []
for doc in docs {
if doc.id.has_prefix(prefix) {
result.push(doc)
}
}
result
}
///|
/// Remove duplicate ids, keeping the first document for each id.
pub fn deduplicate_documents(docs : Array[Document]) -> Array[Document] {
let seen = Map([])
let result = []
for doc in docs {
if !seen.contains(doc.id) {
seen.set(doc.id, true)
result.push(doc)
}
}
result
}
///|
/// Return the vector norms in document order.
pub fn document_norms(
docs : Array[Document],
) -> Array[Double] raise VectorError {
let norms = []
for doc in docs {
norms.push(vector_norm(doc.vector))
}
norms
}
///|
/// Return a copy with all vectors transformed by a scalar.
pub fn scale_documents(
docs : Array[Document],
scalar : Double,
) -> Array[Document] raise VectorError {
let result = []
for doc in docs {
result.push(
Document::new(doc.id, vector_scale(doc.vector, scalar), doc.metadata),
)
}
result
}
///|
/// Return all vectors as independent arrays for numerical processing.
pub fn document_vectors(docs : Array[Document]) -> Array[Array[Double]] {
let result = []
for doc in docs {
let vector = Array::make(doc.vector.length(), 0.0)
for i = 0; i < doc.vector.length(); i = i + 1 {
vector[i] = doc.vector[i]
}
result.push(vector)
}
result
}
///|
/// Add a deterministic ordinal metadata field to a corpus.
pub fn annotate_ordinals(
docs : Array[Document],
key : String,
) -> Array[Document] {
let result = []
for i = 0; i < docs.length(); i = i + 1 {
result.push(set_metadata(docs[i], key, i.to_string()))
}
result
}