Skip to content

Commit

Permalink
Add average methods
Browse files Browse the repository at this point in the history
  • Loading branch information
gammasoft71 committed Dec 25, 2024
1 parent c645049 commit b10045b
Show file tree
Hide file tree
Showing 6 changed files with 241 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/xtd.core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,7 @@ add_sources(
src/xtd/io/string_writer.cpp
src/xtd/io/text_reader.cpp
src/xtd/io/text_writer.cpp
src/xtd/linq/enumerable.cpp
src/xtd/media/system_sound.cpp
src/xtd/media/system_sounds.cpp
src/xtd/net/cookie_exception.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,13 @@ namespace xtd {
xtd::linq::enumerable_collection<source_t> as_enumerable() const noexcept {
return xtd::linq::enumerable::as_enumerable(base());
}

/// @brief Computes the average of a sequence of source_t values.
/// @return The average of this sequence of values.
/// @exception xtd::invalid_operation_exception this sequence contains no elements.
auto average() const noexcept {
return xtd::linq::enumerable::average(base());
}
/// @}

private:
Expand Down
54 changes: 54 additions & 0 deletions src/xtd.core/include/xtd/linq/enumerable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
#pragma once
#include "enumerable_collection.hpp"
#include "../collections/generic/helpers/allocator.hpp"
#include "../decimal.hpp"
#include "../iequatable.hpp"
#include "../int32.hpp"
#include "../int64.hpp"
#include "../optional.hpp"
#include "../static.hpp"
#include <algorithm>
#include <functional>
Expand Down Expand Up @@ -728,7 +732,57 @@ namespace xtd {
result.items.push_back(*iterator);
return result;
}

/// @brief Computes the average of a sequence of xtd::decimal values.
/// @param source A sequence of xtd::decimal values to calculate the average of.
/// @return The average of the sequence of values.
/// @exception xtd::invalid_operation_exception `source` contains no elements.
static xtd::decimal average(const xtd::collections::generic::ienumerable<xtd::decimal>& source);
/// @brief Computes the average of a sequence of double values.
/// @param source A sequence of double values to calculate the average of.
/// @return The average of the sequence of values.
/// @exception xtd::invalid_operation_exception `source` contains no elements.
static double average(const xtd::collections::generic::ienumerable<double>& source);
/// @brief Computes the average of a sequence of float values.
/// @param source A sequence of float values to calculate the average of.
/// @return The average of the sequence of values.
/// @exception xtd::invalid_operation_exception `source` contains no elements.
static float average(const xtd::collections::generic::ienumerable<float>& source);
/// @brief Computes the average of a sequence of xtd::int32 values.
/// @param source A sequence of xtd::int32 values to calculate the average of.
/// @return The average of the sequence of values.
/// @exception xtd::invalid_operation_exception `source` contains no elements.
static double average(const xtd::collections::generic::ienumerable<xtd::int32>& source);
/// @brief Computes the average of a sequence of xtd::int64 values.
/// @param source A sequence of xtd::int64 values to calculate the average of.
/// @return The average of the sequence of values.
/// @exception xtd::invalid_operation_exception `source` contains no elements.
static double average(const xtd::collections::generic::ienumerable<xtd::int64>& source);

/// @brief Computes the average of a sequence of optional xtd::decimal values.
/// @param source A sequence of optional xtd::decimal values to calculate the average of.
/// @return The average of the sequence of values, or xtd::nullopt if the source sequence is empty or contains only values that are xtd::nullopt.
static xtd::optional<xtd::decimal> average(const xtd::collections::generic::ienumerable<xtd::optional<xtd::decimal>>& source) noexcept;
/// @brief Computes the average of a sequence of optional double values.
/// @param source A sequence of optional double values to calculate the average of.
/// @return The average of the sequence of values, or xtd::nullopt if the source sequence is empty or contains only values that are xtd::nullopt.
static xtd::optional<double> average(const xtd::collections::generic::ienumerable<xtd::optional<double>>& source) noexcept;
/// @brief Computes the average of a sequence of optional float values.
/// @param source A sequence of optional float values to calculate the average of.
/// @return The average of the sequence of values, or xtd::nullopt if the source sequence is empty or contains only values that are xtd::nullopt.
static xtd::optional<float> average(const xtd::collections::generic::ienumerable<xtd::optional<float>>& source) noexcept;
/// @brief Computes the average of a sequence of optional xtd::int32 values.
/// @param source A sequence of optional xtd::int32 values to calculate the average of.
/// @return The average of the sequence of values, or xtd::nullopt if the source sequence is empty or contains only values that are xtd::nullopt.
static xtd::optional<double> average(const xtd::collections::generic::ienumerable<xtd::optional<xtd::int32>>& source) noexcept;
/// @brief Computes the average of a sequence of optional xtd::int64 values.
/// @param source A sequence of optional xtd::int64 values to calculate the average of.
/// @return The average of the sequence of values, or xtd::nullopt if the source sequence is empty or contains only values that are xtd::nullopt.
static xtd::optional<double> average(const xtd::collections::generic::ienumerable<xtd::optional<xtd::int64>>& source) noexcept;
/// @}

private:
void throw_invalid_operation_exception();
};
}
}
127 changes: 127 additions & 0 deletions src/xtd.core/src/xtd/linq/enumerable.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#include "../../../include/xtd/linq/enumerable.hpp"
#include "../../../include/xtd/as.hpp"
#include "../../../include/xtd/invalid_operation_exception.hpp"
#include "../../../include/xtd/literals.hpp"

using namespace xtd;
using namespace xtd::collections::generic;
using namespace xtd::linq;

decimal enumerable::average(const ienumerable<decimal>& source) {
auto average = .0l;
auto count = 0;
for (auto item : source) {
average += item;
++count;
}
if (count == 0) throw invalid_operation_exception {};
return average / count;
}

double enumerable::average(const ienumerable<double>& source) {
auto average = .0;
auto count = 0;
for (auto item : source) {
average += item;
++count;
}
if (count == 0) throw invalid_operation_exception {};
return average / count;
}

float enumerable::average(const ienumerable<float>& source) {
auto average = .0f;
auto count = 0;
for (auto item : source) {
average += item;
++count;
}
if (count == 0) throw invalid_operation_exception {};
return average / count;
}

double enumerable::average(const ienumerable<int32>& source) {
auto average = .0;
auto count = 0;
for (auto item : source) {
average += as<double>(item);
++count;
}
if (count == 0) throw invalid_operation_exception {};
return average / count;
}

double enumerable::average(const ienumerable<int64>& source) {
auto average = .0;
auto count = 0;
for (auto item : source) {
average += as<double>(item);
++count;
}
if (count == 0) throw invalid_operation_exception {};
return average / count;
}

optional<decimal> enumerable::average(const ienumerable<optional<decimal>>& source) noexcept {
auto average = .0l;
auto count = 0;
for (auto item : source) {
if (!item.has_value()) continue;
average += item.value();
++count;
}
if (count == 0) return nullopt;
return average / count;
}

optional<double> enumerable::average(const ienumerable<optional<double>>& source) noexcept {
auto average = .0;
auto count = 0;
for (auto item : source) {
if (!item.has_value()) continue;
average += item.value();
++count;
}
if (count == 0) return nullopt;
return average / count;
}

optional<float> enumerable::average(const ienumerable<optional<float>>& source) noexcept {
auto average = .0f;
auto count = 0;
for (auto item : source) {
if (!item.has_value()) continue;
average += item.value();
++count;
}
if (count == 0) return nullopt;
return average / count;
}

optional<double> enumerable::average(const ienumerable<optional<int32>>& source) noexcept {
auto average = .0;
auto count = 0;
for (auto item : source) {
if (!item.has_value()) continue;
average += as<double>(item.value());
++count;
}
if (count == 0) return nullopt;
return average / count;
}

optional<double> enumerable::average(const ienumerable<optional<int64>>& source) noexcept {
auto average = .0;
auto count = 0;
for (auto item : source) {
if (!item.has_value()) continue;
average += as<double>(item.value());
++count;
}
if (count == 0) return nullopt;
return average / count;
}

void enumerable::throw_invalid_operation_exception() {
throw invalid_operation_exception {};
}
2 changes: 1 addition & 1 deletion tests/xtd.core.manual_tests/src/manual_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using namespace xtd;

auto main() -> int {
println("Hello, World!");
println("average = {}", array<int> {1, 2, 3, 4, 5}.average());

/*
try {
Expand Down
51 changes: 51 additions & 0 deletions tests/xtd.core.unit_tests/src/xtd/linq/tests/enumerable_tests.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <xtd/linq/enumerable>
#include <xtd/icomparable>
#include <xtd/invalid_operation_exception>
#include <xtd/tunit/collection_assert>
#include <xtd/tunit/assert>
#include <xtd/tunit/test_class_attribute>
Expand Down Expand Up @@ -129,5 +130,55 @@ namespace xtd::linq::tests {
assert::is_instance_of<xtd::linq::enumerable_collection<int>>(enumerable::as_enumerable<int>(s.begin(), s.end()));
collection_assert::are_equal({1, 2, 3}, enumerable::as_enumerable<int>(s.begin(), s.end()));
}

void test_method_(average_with_enumerable_decimal) {
assert::are_equal(.3l, enumerable::average(array {.1l, .2l, .3l, .4l, .5l}));
assert::throws<invalid_operation_exception>([]{enumerable::average(array<decimal> {});});
}

void test_method_(average_with_enumerable_double) {
assert::are_equal(.3, enumerable::average(array {.1, .2, .3, .4, .5}));
assert::throws<invalid_operation_exception>([]{enumerable::average(array<double> {});});
}

void test_method_(average_with_enumerable_float) {
assert::are_equal(.3f, enumerable::average(array {.1f, .2f, .3f, .4f, .5f}));
assert::throws<invalid_operation_exception>([]{enumerable::average(array<float> {});});
}

void test_method_(average_with_enumerable_int32) {
assert::are_equal(3.0, enumerable::average(array {1, 2, 3, 4, 5}));
assert::throws<invalid_operation_exception>([]{enumerable::average(array<int32> {});});
}

void test_method_(average_with_enumerable_int64) {
assert::are_equal(3.0, enumerable::average(array {1_s64, 2_s64, 3_s64, 4_s64, 5_s64}));
assert::throws<invalid_operation_exception>([]{enumerable::average(array<int64> {});});
}

void test_method_(average_with_enumerable_optional_decimal) {
assert::are_equal(.3l, enumerable::average(array<optional<decimal>> {.1l, .2l, nullopt, .3l, .4l, .5l}));
assert::are_equal(nullopt, enumerable::average(array<optional<decimal>> {}));
}

void test_method_(average_with_enumerable_optional_double) {
assert::are_equal(.3, enumerable::average(array<optional<double>> {.1, .2, nullopt, .3, .4, .5}));
assert::are_equal(nullopt, enumerable::average(array<optional<double>> {}));
}

void test_method_(average_with_enumerable_optional_float) {
assert::are_equal(.3f, enumerable::average(array<optional<float>> {.1f, .2f, nullopt, .3f, .4f, .5f}));
assert::are_equal(nullopt, enumerable::average(array<optional<float>> {}));
}

void test_method_(average_with_enumerable_optional_int32) {
assert::are_equal(3.0, enumerable::average(array<optional<int32>> {1, 2, nullopt, 3, 4, 5}));
assert::are_equal(nullopt, enumerable::average(array<optional<int32>> {}));
}

void test_method_(average_with_enumerable_optional_int64) {
assert::are_equal(3.0, enumerable::average(array<optional<int64>> {1_s64, 2_s64, nullopt, 3_s64, 4_s64, 5_s64}));
assert::are_equal(nullopt, enumerable::average(array<optional<int64>> {}));
}
};
}

0 comments on commit b10045b

Please sign in to comment.