Split emoji string in Dart - string

I want to split a string of emojis into each emoji. so how can I do this in dart language?
void main() {
print('GoodJob'.split("")); // output: [G, o, o, d, J, o, b]
print('πŸ€­πŸŽ±πŸ“'.split("")); // output: [οΏ½, οΏ½, οΏ½, οΏ½, οΏ½, οΏ½] but expected: ['🀭','🎱','πŸ“']
}

Docs from TextField recommends to use characters package to work with emoji in dart.
Docs describe as follows,
It's important to always use characters when dealing with user input text that may contain complex characters. This will ensure that extended grapheme clusters and surrogate pairs are treated as single characters, as they appear to the user.
For example, when finding the length of some user input, use string.characters.length. Do NOT use string.length or even string.runes.length. For the complex character "πŸ‘¨β€πŸ‘©β€πŸ‘¦", this appears to the user as a single character, and string.characters.length intuitively returns 1. On the other hand, string.length returns 8, and string.runes.length returns 5!
import 'package:characters/characters.dart';
void main() {
print('πŸ€­πŸŽ±πŸ“'.characters.split("".characters));
}
outputs
(🀭, 🎱, πŸ“)

You can match all the emojis using regex, and then add them to a list:
List<String> splitEmoji(String text) {
final List<String> out = [];
final pattern = RegExp(
r'(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])');
final matches = pattern.allMatches(text);
for (final match in matches) {
out.add(match.group(0)!);
}
return out;
}
Regex credit
Usage:
print(splitEmoji('πŸ€­πŸŽ±πŸ“')); // Output: [🀭, 🎱, πŸ“]

You can use the runes property of String.
void main() {
final String emojis = 'πŸ€­πŸŽ±πŸ“';
final Runes codePoints = emojis.runes;
for (final codePoint in codePoints) {
print(String.fromCharCode(codePoint));
}
}

Related

How to set maximum length in String value DART

i am trying to set maximum length in string value and put '..' instead of removed chrs like following
String myValue = 'Welcome'
now i need the maximum length is 4 so output like following
'welc..'
how can i handle this ? thanks
The short and incorrect version is:
String abbrevBad(String input, int maxlength) {
if (input.length <= maxLength) return input;
return input.substring(0, maxLength - 2) + "..";
}
(Using .. is not the typographical way to mark an elision. That takes ..., the "ellipsis" symbol.)
A more internationally aware version would count grapheme clusters instead of code units, so it handles complex characters and emojis as a single character, and doesn't break in the middle of one. Might also use the proper ellipsis character.
String abbreviate(String input, int maxLength) {
var it = input.characters.iterator;
for (var i = 0; i <= maxLength; i++) {
if (!it.expandNext()) return input;
}
it.dropLast(2);
return "${it.current}\u2026";
}
That also works for characters which are not single code units:
void main() {
print(abbreviate("argelbargle", 7)); // argelb…
print(abbreviate("πŸ‡©πŸ‡°πŸ‡©πŸ‡°πŸ‡©πŸ‡°πŸ‡©πŸ‡°πŸ‡©πŸ‡°", 4)); // πŸ‡©πŸ‡°πŸ‡©πŸ‡°πŸ‡©πŸ‡°β€¦
}
(If you want to use ... instead of …, just change .dropLast(2) to .dropLast(4) and "…" to "...".)
You need to use RichText and you need to specify the overflow type, just like this:
Flexible(
child: RichText("Very, very, very looong text",
overflow: TextOverflow.ellipsis,
),
);
If the Text widget overflows, some points (...) will appears.

Replace some characters in a string with the next unicode character

I have an input text as following:
inputtext = "This is a test";
I need to replace some of the character (based on a certain criteria) to next unicode character
let i = 0;
for c in inputtext.chars() {
if (somecondition){
// Replace char here
inputtext.replace_range(i..i+1, newchar);
// println!("{}", c);
}
What is the best way to do this?
You can't easily update a string in-place because a Rust string is not just an array of characters, it's an array of bytes (in UTF-8 encoding), and different characters may use different numbers of bytes. For example, the character ίΏ (U+07FF "Nko Taman Sign") uses two bytes, whereas the next Unicode character ΰ € (U+0800 "Samaritan Letter Alaf") uses three.
It's therefore simplest to turn the string into an iterator of characters (using .chars()), manipulate that iterator as appropriate, and then construct a new string using .collect().
For example:
let old = "abcdef";
let new = old.chars()
// note: there's an edge case if ch == char::MAX which we must decide
// how to handle. in this case I chose to not change the
// character, but this may be different from what you need.
.map(|ch| {
if somecondition {
char::from_u32(ch as u32 + 1).unwrap_or(ch)
} else {
ch
}
})
.collect::<String>();

Get String Between 2 Strings with Arduino

I am looking for a way to get a String between 2 Strings using Arduino. This is the source String:
Hello, my name is John Doe# and my favourite number is 32#.
The output has to be:
String name = "John Doe"; //Between "name is " and "#"
String favouriteNumber = "32"; //Between "number is " and "#"
How can this be achieved with Arduino?
I am not able to find any information online about this. Those examples for C are not working anyway. I understand that using String is not recommended in Arduino, but I have to do it this way to make things simpler.
By the way, this method of using a '#' to indicate the end of the data is not an ideal way to do it as I would like the input to be more human readable and more natural. Would anyone please suggest another way to do this as well?
Thanks in advance!
Function midString find the substring that is between two other strings "start" and "finish". If such a string does not exist, it returns "". A test code is included too.
void setup() {
test();
}
void loop() {
delay(100);
}
String midString(String str, String start, String finish){
int locStart = str.indexOf(start);
if (locStart==-1) return "";
locStart += start.length();
int locFinish = str.indexOf(finish, locStart);
if (locFinish==-1) return "";
return str.substring(locStart, locFinish);
}
void test(){
Serial.begin(115200);
String str = "Get a substring of a String. The starting index is inclusive (the corresponding character is included in the substring), but the optional ending index is exclusive";
Serial.print(">");
Serial.print( midString( str, "substring", "String" ) );
Serial.println("<");
Serial.print(">");
Serial.print( midString( str, "substring", "." ) );
Serial.println("<");
Serial.print(">");
Serial.print( midString( str, "corresponding", "inclusive" ) );
Serial.println("<");
Serial.print(">");
Serial.print( midString( str, "object", "inclusive" ) );
Serial.println("<");
}
just searched for this and saw no answer so i cooked one up.
i prefer working with String as well because of code readability and simplicity.
for me its more important than squeezing every last drop of juice out of my arduino.
String name = GetStringBetweenStrings("Hello, my name is John Doe# and my favourite number is 32#." ,"name is ","#");
String GetStringBetweenStrings(String input, String firstdel, String enddel){
int posfrom = input.indexOf(firstdel) + firstdel.length();
int posto = input.indexOf(enddel);
return input.substring(posfrom, posto);
}
watch out for the first case its fine, but for the second one you would have to change the second filter sting to "#." so it doesn't use the first occurrence of the #

How to collect a string to a stack of characters in Java 8? [duplicate]

I would like to convert the string containing abc to a list of characters and a hashset of characters. How can I do that in Java ?
List<Character> charList = new ArrayList<Character>("abc".toCharArray());
In Java8 you can use streams I suppose.
List of Character objects:
List<Character> chars = str.chars()
.mapToObj(e->(char)e).collect(Collectors.toList());
And set could be obtained in a similar way:
Set<Character> charsSet = str.chars()
.mapToObj(e->(char)e).collect(Collectors.toSet());
You will have to either use a loop, or create a collection wrapper like Arrays.asList which works on primitive char arrays (or directly on strings).
List<Character> list = new ArrayList<Character>();
Set<Character> unique = new HashSet<Character>();
for(char c : "abc".toCharArray()) {
list.add(c);
unique.add(c);
}
Here is an Arrays.asList like wrapper for strings:
public List<Character> asList(final String string) {
return new AbstractList<Character>() {
public int size() { return string.length(); }
public Character get(int index) { return string.charAt(index); }
};
}
This one is an immutable list, though. If you want a mutable list, use this with a char[]:
public List<Character> asList(final char[] string) {
return new AbstractList<Character>() {
public int size() { return string.length; }
public Character get(int index) { return string[index]; }
public Character set(int index, Character newVal) {
char old = string[index];
string[index] = newVal;
return old;
}
};
}
Analogous to this you can implement this for the other primitive types.
Note that using this normally is not recommended, since for every access you
would do a boxing and unboxing operation.
The Guava library contains similar List wrapper methods for several primitive array classes, like Chars.asList, and a wrapper for String in Lists.charactersOf(String).
The lack of a good way to convert between a primitive array and a collection of its corresponding wrapper type is solved by some third party libraries. Guava, a very common one, has a convenience method to do the conversion:
List<Character> characterList = Chars.asList("abc".toCharArray());
Set<Character> characterSet = new HashSet<Character>(characterList);
Use a Java 8 Stream.
myString.chars().mapToObj(i -> (char) i).collect(Collectors.toList());
Breakdown:
myString
.chars() // Convert to an IntStream
.mapToObj(i -> (char) i) // Convert int to char, which gets boxed to Character
.collect(Collectors.toList()); // Collect in a List<Character>
(I have absolutely no idea why String#chars() returns an IntStream.)
The most straightforward way is to use a for loop to add elements to a new List:
String abc = "abc";
List<Character> charList = new ArrayList<Character>();
for (char c : abc.toCharArray()) {
charList.add(c);
}
Similarly, for a Set:
String abc = "abc";
Set<Character> charSet = new HashSet<Character>();
for (char c : abc.toCharArray()) {
charSet.add(c);
}
List<String> result = Arrays.asList("abc".split(""));
Create an empty list of Character and then make a loop to get every character from the array and put them in the list one by one.
List<Character> characterList = new ArrayList<Character>();
char arrayChar[] = abc.toCharArray();
for (char aChar : arrayChar)
{
characterList.add(aChar); // autoboxing
}
You can do this without boxing if you use Eclipse Collections:
CharAdapter abc = Strings.asChars("abc");
CharList list = abc.toList();
CharSet set = abc.toSet();
CharBag bag = abc.toBag();
Because CharAdapter is an ImmutableCharList, calling collect on it will return an ImmutableList.
ImmutableList<Character> immutableList = abc.collect(Character::valueOf);
If you want to return a boxed List, Set or Bag of Character, the following will work:
LazyIterable<Character> lazyIterable = abc.asLazy().collect(Character::valueOf);
List<Character> list = lazyIterable.toList();
Set<Character> set = lazyIterable.toSet();
Bag<Character> set = lazyIterable.toBag();
Note: I am a committer for Eclipse Collections.
IntStream can be used to access each character and add them to the list.
String str = "abc";
List<Character> charList = new ArrayList<>();
IntStream.range(0,str.length()).forEach(i -> charList.add(str.charAt(i)));
Using Java 8 - Stream Funtion:
Converting A String into Character List:
ArrayList<Character> characterList = givenStringVariable
.chars()
.mapToObj(c-> (char)c)
.collect(collectors.toList());
Converting A Character List into String:
String givenStringVariable = characterList
.stream()
.map(String::valueOf)
.collect(Collectors.joining())
To get a list of Characters / Strings -
List<String> stringsOfCharacters = string.chars().
mapToObj(i -> (char)i).
map(c -> c.toString()).
collect(Collectors.toList());

Groovy collect over a String

When I collect over a String I was expecting that it would be of type char, but it is java.lang.String. So why is this and how can I collect all characters of a String?
You can do something like this...
someString.collect {
def c = it as char
// carry on...
}
Or...
someString.chars.collect {
// it will be a char
// carry on...
}
In Groovy, a single character is also a String. In order to get each String as a Character use as:
"testString".collect { it as char }

Resources