Skip to content

Latest commit

 

History

History
103 lines (72 loc) · 3.93 KB

commafy.md

File metadata and controls

103 lines (72 loc) · 3.93 KB
title timestamp author published description tags todo
Commafy - add a comma after every 3 digits
2023-12-06 10:30:01 -0800
szabgab
true
A number like this: 1234567890 is quite unreadable 1,234,567,890 is much better.
commafy
assert_eq!
into
abs
thousands
release as a crate
use this crate in the liquid commafy example

A number like this: 1234567890 is quite unreadable 1,234,567,890 is much better.

Converting a number to this more readable form is sometimes called commafy. Here is an implementation:

{% include file="examples/commafy/src/main.rs" %}

  • We have function called get_command_line_number taken from the example expecting one command line parameter.

  • We also have a main function to make it easier to try the code on the command line.

  • We also have a bunch of tests at the bottom of the file. We can run the tests by typing in cargo test. In each test-case we call the commafy function and then compare the resulting string with the expected string on the right hand side. We use the assert_eq! functions for this.

  • The real code is in the commafy function.

Explanation

number: Integer

means the function is expecting a single parameter of type Integer. This name refers to any type that fulfills the requirements in the declaration of the type right after the name of the function:

Integer: Into<i128> + Copy + std::fmt::Debug + std::fmt::Display

This means that the newly created Integer type:

  • Must be convertible to i128 without loss. Basically every integer type and unsigned-integer type fulfills this, except u128.
  • Has to have the Copy trait.
  • Has the Debug trait.
  • And the Display trait.

The function will return a String.

We only want to work with non-negative numbers, so we work with the absolute value, but the Integer type we created does not have the abs methods so first we need to call the into method to convert the value to i128.

let num = number.into().abs();

We actually want to work with characters, disregarding the numerical values so we convert the number into a string.

let num = format!("{num}");

It would be hard to add a comma after every 3 character from the right side (the back) of the string, so we split it up into individual characters (using the chars method, then reverse the characters using the rev method.

Then using map we go over each character and add a comma (,) after each 3rd character. Actually, we add a comma in-front the character whose index is 1 modulo 3 (ix % 3 == 1). This way we can make sure that we convert 123456 to 123,456 and not to ,123,456.

The we call collect and provide the type using the turbofish syntax: ```::`.

The result is a string with all the commas.

The prefix is the - for the negative numbers. It is really nice of Rust that if returns the expression in it.

let prefix = if number.into() < 0 { "-" } else { "" };

Finally we need to reverse the string again to get in the correct direction.

format!("{}{}", prefix, num.chars().rev().collect::<String>())

The thousands crate

After implementing this someone pointed me to the thousands crate that does this already and even later I wrote an example using the thousands crate.