1

I want to define a function that takes a parameter that can be iterated over without being consumed. The function should be able to take a Vec but also other iterable objects. I am hung up on how to define a suitable generic parameter with a type constraint that will work. The purpose of the function is to get the maximum and minimum values from among all coordinates of a collection of points. (I store this in i64 because I will create other functions to handle u32 points, and they can get bigger than the largest i32.) The collection is passed in as a slice, but how shall I represent the points? A Vec<i32> will work as shown below, but I want anything that can produce a sequence of i32. Whatever solution is offered, the function must still be callable on a slice of Vecs (or pointers to Vecs) and not consume them.

Here is my code using a slice of Vecs:

use std::iter::{IntoIterator, Iterator};
use std::{i32, u32};

/// The observed range of values seen in a set of points whose coordinates are 32-bit integers (signed or unsigned).
///
/// From this information we can determine how to translate the coordinates so that their normalized range has a low of zero.
/// This permits us to use the fewest number of bits to represent them when constructing a Hilbert index.
pub struct IntegerDataRange {
    pub low: i64,
    pub high: i64,
}

impl IntegerDataRange {
    pub fn from_i32(points: &[Vec<i32>]) -> Self {
        let mut low = i32::MAX as i64;
        let mut high = i32::MIN as i64;
        for point in points.iter() {
            for coordinate in point.iter().map(|c| *c as i64) {
                if coordinate > high {
                    high = coordinate;
                }
                if coordinate < low {
                    low = coordinate;
                }
            }
        }
        IntegerDataRange {
            low: low as i64,
            high: high as i64,
        }
    }
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Paul Chernoch
  • 5,275
  • 3
  • 52
  • 73
  • 1
    It looks like your question might be answered by the answers of [Using generic iterators instead of specific list types](https://stackoverflow.com/q/30630810/155423); [Writing a generic function that takes an iterable container as parameter in Rust](https://stackoverflow.com/q/35940068/155423); [How to write a Rust function that takes an iterator?](https://stackoverflow.com/q/34969902/155423). If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Nov 12 '19 at 18:19
  • 1
    You probably want/can use [`Itertools::minmax`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.minmax) instead. – hellow Nov 12 '19 at 18:19
  • 1
    [The duplicate applied to your case](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=80daad27468c6b9b0dc3b98ca16682ba), and [with itertools](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=5f7a0bb9fa61e227fd72707c9a00e37c). – Shepmaster Nov 12 '19 at 18:32
  • 1
    @Shepmaster, I will look at the other question. - looked. It works! thanks. – Paul Chernoch Nov 12 '19 at 18:41
  • @hellow, while minmax may accomplish what I am showing, I have several other methods that will make use of this information and generate a lambda to be returned. – Paul Chernoch Nov 12 '19 at 18:42
  • @Shepmaster - I had looked at one of the "duplicate" questions before you cited it, attempted to apply what it said, and failed. Only seeing how you implemented it in the Rust Playground helped. I still find applying SO answers related to my problem to my actual situation harder in Rust than in other languages. – Paul Chernoch Nov 12 '19 at 19:20
  • 1
    In the future, it would be a good idea to link to the questions / answers that you have already read and describe what problems you had in applying them, or even ask about the differences between your case and the other cases. That may make the new question distinct from any existing questions, or prompt us to expand on an existing answer with more detail or links, or provide an additional answer. It also helps demonstrate the work that you put in before asking the question, which most answerers appreciate. – Shepmaster Nov 12 '19 at 19:24
  • 1
    Otherwise, an answerer has to make guesses and assumptions about the context you are coming from. We could assume the OP has no knowledge and we have to start from zero, or that they have all of the knowledge but just have a typo, or somewhere in between. It's simpler to point them at potential duplicates and ask them to clarify how the question differs instead of spending a lot of time on an answer that does what the OP wants but might not explain it to them in the exact manner they need. – Shepmaster Nov 12 '19 at 19:27

0 Answers0