I'm not expert in Dart, and above all not in bytes manipulation.
I use flutter_blue and and receive or send list of int like [211, 13, 67].
I read enter link description here which is not intuitive for me but succeed to convert these kind of data into String or number,
but in some cases, I need to convert one byte as its equivalent 8-bits int, or vice versa.
For example : 0100000 -> 0x...., or [165] -> 01111111
Could you help me please ?
Thanks
Does something like this do the job?
void main() {
final list = [211, 13, 67];
for (final number in list) {
print('${intTo8bitString(number)} = $number');
}
// 11010011 = 211
// 00001101 = 13
// 01000011 = 67
for (final number in list) {
print('${intTo8bitString(number, prefix: true)} = $number');
}
// 0x11010011 = 211
// 0x00001101 = 13
// 0x01000011 = 67
print(binaryStringToInt('0x11010011')); // 211
print(binaryStringToInt('1101')); // 13
print(binaryStringToInt('01000011')); // 67
}
String intTo8bitString(int number, {bool prefix = false}) => prefix
? '0x${number.toRadixString(2).padLeft(8, '0')}'
: '${number.toRadixString(2).padLeft(8, '0')}';
final _pattern = RegExp(r'(?:0x)?(\d+)');
int binaryStringToInt(String binaryString) =>
int.parse(_pattern.firstMatch(binaryString)!.group(1)!, radix: 2);
Related
I get Ids in a String format that contain leading zeroes. I would like to keep this String format but without the leading zeroes. Example:
00 => 0
01 => 1
02 => 2
10 => 10
11 => 11
My current implementation is
String id = int.parse(originalId).toString()
Is there a better / efficient / Dart pattern way to achieve this conversion ?
You could use RegExp which may be uglier but faster than double conversion :
"01".replaceAll(new RegExp(r'^0+(?=.)'), '')
´^´ matches the begining of the string
0+ matches one or more 0 character
(=?.) matches a group (()) of any characters except line breaks (.) without including it in the result (=?), this ensures that not the entire string will be matched so that we keep at least one zero if there are only zeroes.
Example :
void main() {
final List nums = ["00", "01", "02", "10", "11"];
final RegExp regexp = new RegExp(r'^0+(?=.)');
for (String s in nums) {
print("$s => ${s.replaceAll(regexp, '')}");
}
}
Result :
00 => 0
01 => 1
02 => 2
10 => 10
11 => 11
EDIT : Performance test thanks to your comment
void main() {
Stopwatch stopwatch = Stopwatch()..start();
final RegExp reg = RegExp(r'^0+(?=.)');
for (int i = 0; i < 20000000; i++) {
'05'.replaceAll(reg, '');
}
print('RegExp executed in ${stopwatch.elapsed}');
stopwatch = Stopwatch()..start();
for (int i = 0; i < 20000000; i++) {
int.parse('05').toString();
}
print('Double conversion executed in ${stopwatch.elapsed}');
}
Result :
RegExp executed in 0:00:02.912000
Double conversion executed in 0:00:03.216000
The more operations you will do the more it will be efficient compared to double conversion. However RegExp may be slower in a single computation because creating it has a cost, but we speak about a few microseconds... I would say that unless you have tens of thousands of operations just use the more convenient to you.
If anyone is trying to prevent leading zeros in a TextField, I made a TextInputFormatter that will remove all leading zeros once a non-zero number is added.
class NoLeadingZeros extends TextInputFormatter {
#override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue,
TextEditingValue newValue,
) {
if (newValue.text.startsWith('0') && newValue.text.length > 1) {
return TextEditingValue().copyWith(
text: newValue.text.replaceAll(new RegExp(r'^0+(?=.)'), ''),
selection: newValue.selection.copyWith(
baseOffset: newValue.text.length - 1,
extentOffset: newValue.text.length - 1,
),
);
} else {
return newValue;
}
}
}
The tricky part is adjusting the TextSelection offsets once the zeros are removed. Without this update, the TextField will stop working.
I think you have the most elegant form already! There options for toStringAsFixed (https://api.dart.dev/stable/1.19.1/dart-core/num/toStringAsFixed.html, mostly floating points) and NumberFormat (https://pub.dev/documentation/intl/latest/intl/NumberFormat-class.html), but I feel these might not cover your case
If you have string value such as "01","001","0230" and If you want to remove leading zero then try this method. Worked for me.
num.parse('001').toInt() // where 001 is a string with leading zero
Thanks, Keep Learning
How can I find the closest value in a list, which will return me the higher value?
Example: List of [3,7,12,19] if my value is 8 how can I get the nearest(larger) value 12? i want this logic in dart.
Just filter the List only for the values higher or equal to your number and get the lowest value:
var n = 8; // Number to match
var l = [3, 7, 12, 19]; // List of values
var greater = l.where((e) => e >= n).toList()..sort(); //List of the greater values
print(greater.first); // Print the first value. -> 12
To get Closest Value of number
import 'dart:math';
import 'dart:collection';
void main(){
List<double> value = [1,4,6,3,7,9,12,34,12,-12,-91];
print(value.getCloseValue(8)); // 7
print(value.getCloseValue(6)); // 6
print(value.getCloseValue(-11)); // -12
}
extension on List<num> {
num getCloseValue(num x) {
if (isEmpty) return 0;
Map<num, num> values = {};
forEach((e) {
values[e] = (e - x).abs();
});
var sortedKeys = values.keys.toList(growable:false)
..sort((k1, k2) => values[k1]!.compareTo(values[k2]!));
final sortedMap = LinkedHashMap
.fromIterable(sortedKeys, key: (k) => k, value: (k) => values[k]);
return sortedMap.keys.first;
}
}
List<int> arr = [6, 12, 11, 18, 24,5,6,99,10,9];
arr.sort((a, b) => a.compareTo(b));
print(arr);
print(Utils.getNextLargerNumber(8, arr));
and below is the logic:
static int getNextLargerNumber(int number, List<int> array)
{
for (var i = 0; i < array.length; i++) {
if (number < array[i]) {
return array[i];
}
}
return -1;
}
Mattia's answer is already good enough. (although the list cant have the length 0 and it might be not as efficient, as you have a where() as well as sort() in there). Here is a different approach, that solves those concerns:
Nearest value to target (larger favored)
final nearestLarger = list.isEmpty ? null : list.reduce(
(a, b) => (a-target).abs() < (b -target).abs() ? a : b);
Nearest value to target (smaller favoured)
final nearestSmaller = list.isEmpty ? null : list.reduce(
(a, b) => (a-target).abs() <= (b -target).abs() ? a : b);
Note that both functions retrieve the nearest value to the target, but in case of ambiguity (eg. [3,4,5]) either the bigger or smaller value is favored.
So I have two lists that I each mapped to get the ints, and then I used a reduce function to total them.
I now need just both those totals in a new list, like a totalsList made up of TotalsEntry's or something.
How can this be done?
List<int> listOfOnlyPrices = [];
List<int> listOfOnlyExpenses = [];
int totalSales;
int totalExpenses;
void totalSalesWidget() {
listOfOnlyPrices = items.map<int>((SaleEntry int) =>
int.price).toList();
totalSales = listOfOnlyPrices.reduce((a, b) => a + b);
}
void totalExpensesWidget() {
listOfOnlyExpenses = expenseList.map<int>((ExpenseEntry int) => int.priceEx).toList();
totalExpenses = listOfOnlyExpenses.reduce((a, b) => a + b);
}
All of this works fine btw. I can use totalSales and totalExpenses already within the app.
If I understand you correctly, the following should already do the job:
List<int> get totalsList => [totalSales, totalExpenses];
How do you get the min and max values of a List in Dart.
[1, 2, 3, 4, 5].min //returns 1
[1, 2, 3, 4, 5].max //returns 5
I'm sure I could a) write a short function or b) copy then sort the list and select the last value,
but I'm looking to see if there is a more native solution if there is any.
Assuming the list is not empty you can use Iterable.reduce :
import 'dart:math';
main(){
print([1,2,8,6].reduce(max)); // 8
print([1,2,8,6].reduce(min)); // 1
}
If you don't want to import dart: math and still wants to use reduce:
main() {
List list = [2,8,1,6]; // List should not be empty.
print(list.reduce((curr, next) => curr > next? curr: next)); // 8 --> Max
print(list.reduce((curr, next) => curr < next? curr: next)); // 1 --> Min
}
You can now achieve this with an extension as of Dart 2.6:
import 'dart:math';
void main() {
[1, 2, 3, 4, 5].min; // returns 1
[1, 2, 3, 4, 5].max; // returns 5
}
extension FancyIterable on Iterable<int> {
int get max => reduce(math.max);
int get min => reduce(math.min);
}
An example to get Min/Max value using reduce based on condition for a list of Map objects
Map studentA = {
'Name': 'John',
'Marks': 85
};
Map studentB = {
'Name': 'Peter',
'Marks': 70
};
List<Map> students = [studentA, studentB];
// Get student having maximum mark from the list
Map studentWithMaxMarks = students.reduce((a, b) {
if (a["Marks"] > b["Marks"])
return a;
else
return b;
});
// Get student having minimum mark from the list (one liner)
Map studentWithMinMarks = students.reduce((a, b) => a["Marks"] < b["Marks"] ? a : b);
Another example to get Min/Max value using reduce based on condition for a list of class objects
class Student {
final String Name;
final int Marks;
Student(this.Name, this.Marks);
}
final studentA = Student('John', 85);
final studentB = Student('Peter', 70);
List<Student> students = [studentA, studentB];
// Get student having minimum marks from the list
Student studentWithMinMarks = students.reduce((a, b) => a.Marks < b.Marks ? a : b);
If your list is empty, reduce will throw an error.
You can use fold instead of reduce.
// nan compare to any number will return false
final initialValue = number.nan;
// max
values.fold(initialValue, (previousValue, element) => element.value > previousValue ? element.value : previousValue);
// min
values.fold(initialValue, (previousValue, element) => element.value < previousValue ? element.value : previousValue);
It can also use to calculate sum.
final initialValue = 0;
values.fold(initialValue, (previousValue, element) => element.value + previousValue);
Although fold is not cleaner than reduce for getting min/max, it is still a powerful method to do more flexible actions.
For empty lists: This will return 0 if list is empty, the max value otherwise.
List<int> x = [ ];
print(x.isEmpty ? 0 : x.reduce(max)); //prints 0
List<int> x = [1,32,5];
print(x.isEmpty ? 0 : x.reduce(max)); //prints 32
int minF() {
final mass = [1, 2, 0, 3, 5];
mass.sort();
return mass[0];
}
void main() {
firstNonConsecutive([1,2,3,4,6,7,8]);
}
int? firstNonConsecutive(List<int> arr) {
var max = arr.reduce((curr, next) => curr > next? curr: next);
print(max); // 8 --> Max
var min = arr.reduce((curr, next) => curr < next? curr: next);
print(min); // 1 --> Min
return null;
}
If you need a more sophisticated min/max, such as finding an object with a min/max of a field, or use of a comparison predicate, use minBy() and maxBy() from the collection package:
import 'package:collection/collection.dart';
class Person {
final String name;
final int age;
Person(this.name, this.age);
#override
String toString() => '$name (age $age)';
}
main() {
final alice = Person('Alice', 30);
final bob = Person('Bob', 40);
final chris = Person('Chris', 25);
final dan = Person('Dan', 35);
final people = [alice, bob, chris, dan];
print('Youngest is ${minBy(people, (e) => e.age)}');
print('Oldest is ${maxBy(people, (e) => e.age)}');
print('First alphabetically is ${minBy(people, (e) => e.name)}');
print('Last alphabetically is ${maxBy(people, (e) => e.name)}');
print('Largest name length times age is ${maxBy(people, (e) => e, compare: (a, b) => (a.name.length * a.age).compareTo(b.name.length * b.age))}');
}
Output:
Youngest is Chris (age 25)
Oldest is Bob (age 40)
First alphabetically is Alice (age 30)
Last alphabetically is Dan (age 35)
Largest name length times age is Alice (age 30)```
I'm creating an application which will create a large number of folders on a web server, with files inside of them.
I need the folder name to be unique. I can easily do this with a GUID, but I want something more user friendly. It doesn't need to be speakable by users, but should be short and standard characters (alphas is best).
In short: i'm looking to do something like Bit.ly does with their unique names:
www.mydomain.com/ABCDEF
Is there a good reference on how to do this? My platform will be .NET/C#, but ok with any help, references, links, etc on the general concept, or any overall advice to solve this task.
Start at 1. Increment to 2, 3, 4, 5, 6, 7,
8, 9, a, b...
A, B, C...
X, Y, Z, 10, 11, 12, ... 1a, 1b,
You get the idea.
You have a synchronized global int/long "next id" and represent it in base 62 (numbers, lowercase, caps) or base 36 or something.
I'm assuming that you know how to use your web server's redirect capabilities. If you need help, just comment :).
The way I would do it would be generating a random integer (between the integer values of 'a' and 'z'); converting it into a char; appending it to a string; and repeating until we reach the needed length. If it generates a value already in the database, repeat the process. If it was unique, store it in the database with the name of the actual location and the name of the alias.
This is a bit hack-like because it assumes that 'a' through 'z' are actually in sequence in their integer values.
Best I could think of :(.
In Perl, without modules so you can translate more easly.
sub convert_to_base {
my ($n, $b) = #_;
my #digits;
while ($n) {
my $digits = $n % $b;
unshift #digits, $digit;
$n = ($n - $digit) / $b;
}
unshift #digits, 0 if !#digits;
return #digits;
}
# Whatever characters you want to use.
my #digit_set = ( '0'..'9', 'a'..'z', 'A'..'Z' );
# The id of the record in the database,
# or one more than the last id you generated.
my $id = 1;
my $converted =
join '',
map { $digit_set[$_] }
convert_to_base($id, 0+#digits_set);
I needed something similar to what you're trying to accomplish. I retooled my code to generate folders so try this. It's setup for a console app, but you can use it in a website also.
private static void genRandomFolders()
{
string basepath = "C:\\Users\\{username here}\\Desktop\\";
int count = 5;
int length = 8;
List<string> codes = new List<string>();
int total = 0;
int i = count;
Random rnd = new Random();
while (i-- > 0)
{
string code = RandomString(rnd, length);
if (!codes.Exists(delegate(string c) { return c.ToLower() == code.ToLower(); }))
{
//Create directory here
System.IO.Directory.CreateDirectory(basepath + code);
}
total++;
if (total % 100 == 0)
Console.WriteLine("Generated " + total.ToString() + " random folders...");
}
Console.WriteLine();
Console.WriteLine("Generated " + total.ToString() + " total random folders.");
}
public static string RandomString(Random r, int len)
{
//string str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; //uppercase only
//string str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; //All
string str = "abcdefghjkmnpqrstuvwxyz123456789"; //Lowercase only
StringBuilder sb = new StringBuilder();
while ((len--) > 0)
sb.Append(str[(int)(r.NextDouble() * str.Length)]);
return sb.ToString();
}