Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unique Value Utilities #464

Merged
merged 3 commits into from
Nov 7, 2023
Merged

Unique Value Utilities #464

merged 3 commits into from
Nov 7, 2023

Conversation

akleeman
Copy link
Collaborator

@akleeman akleeman commented Nov 4, 2023

A common problem is to start with some data, and wonder which unique fields the data contains. You might, for example, do

struct Foo {
  double bar;
}

std::set<double> unique_bars(const std::vector<Foo> &foos) {
  std::set<double> bars;
  for (const auto &f : foos) {
    bars.emplace(f.bar);
  }
  return bars;
}

this PR adds some helper functions which let you do things like:

auto get_bar = [](const auto &f) { return f.bar; };
const auto bars = unique_values(foos, get_bar);

If you think that all the values in a vector contain a shared field and you'd like to get the value (and assert that there is in fact only one) you can do:

auto get_bar = [](const auto &f) { return f.bar; };
const double unique_bar = unique_value(foos, get_bar);

or if there are lots of duplicate Foo types in the vector (and Foo has a < operator) you can do:

const auto unique_foos = unique_values(foos);

the function was named unique_values to avoid conflicting with std::unique which doesn't quite do the same thing. std::unique will return a new iterator which has collapsed neighboring unique values, for example:

  std::vector<int> foo = {1, 3, 2, 2, 1, 5};

  std::vector<int> copy(foo);
  const auto last = std::unique(copy.begin(), copy.end());
  copy.erase(last, copy.end());
  // copy = 1,3,2,1,5

  const auto unique_vals = unique_values(foo);
  // unique_vals = 1, 2, 3, 5

@akleeman akleeman requested a review from peddie November 4, 2023 00:24
Copy link
Contributor

@peddie peddie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to capture this pattern.


template <typename ValueType>
inline ValueType unique_value(const std::set<ValueType> &values) {
assert(values.size() == 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nit: I don't know whether we have a general policy on this, but so far I've often found asserts like assert(values.size == 1 && "expected only one unique value") to be helpful.

@akleeman akleeman merged commit 33caa95 into master Nov 7, 2023
9 checks passed
@akleeman akleeman deleted the akleeman/unique branch November 7, 2023 00:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants