I need to do splitting string before the second occurrence ("-").
Example: s1-qwe-123
need to get: s1-qwe
What is the best practice?
Ehm, thanks, but faced with situation where some files have structure like:
s1-123. And I need to get from them: s1.
Is there any way to make variant with split process such situation?
int saw;
auto s = "s1-qwe-123".findSplitBefore!(c => c == '-' && saw++ > 0)[0];
You could split it and join it together again.
string line = "s1-qwe-123";
string interestedBit = line.split("-")[0..2].join("-");
Or a loop through the chars:
int idx;
bool found;
string line = "s1-qwe-123";
for(idx = 0; idx < line.length; ++idx){
if(line[idx] == '-')
if(found)
break;
else
found = true;
}
auto interestedBit = line[0..idx];
My original answer was completely wrong as I misread the question. Here is a correct answer that provides a slight variation on the split solution already suggested in other answers:
import std.algorithm : splitter;
import std.array : join;
import std.range : take;
auto res = "s1-qwe-123".splitter("-").take(2).join('-');
assert(res == "s1-qwe");
The advantage of using splitter over split is lazy evaluation. This should only walk up to the second '-' and no further.
There are many ways to achieve this, I'll present two.
The first would be to split the whole string by "-" and then to join the first two elements:
import std.stdio, std.string;
"s1-qwe-123".split("-")[0 .. 2]
.join("-")
.writeln; // -> "s1-qwe"
This is simple but may not be efficient enough as the whole string has to be read. The other method I would propose is to use regular expressions as there is a matchFirst function that reads the string only up to the first occurence of the expression.
import std.stdio, std.regex;
"s1-qwe-123".matchFirst("[^-]+-[^-]+")[0]
.writeln; // -> "s1-qwe"
And if you want it to be really fast you can use a compile-time regular expression:
import std.stdio, std.regex;
"s1-qwe-123".matchFirst(ctRegex!("[^-]+-[^-]+"))[0]
.writeln; // -> "s1-qwe"
Related
So the idea here is that I'm taking a .csv into a string and each value needs to be stored into a variable. I am unsure how to properly parse a string to do this.
My idea is a function that looks like
final char delim = ',';
int nextItem(String data, int startFrom) {
if (data.charAt(startFrom) != delim) {
return data.charAt(startFrom)
} else {
return nextItem(data, startFrom + 1);
}
}
so if I passed it something like
nextItem("45,621,9", 0);
it would return 45
and if I passed it
nextItem("45,621,9", 3);
it would return 621
I'm not sure if I have that setup properly to be recursive, but I could also use a For loop I suppose, only real stipulation is I can't use the Substring method.
Please don't use recursion for a matter that can be easily done iteratively. Recursion is expensive in terms of stack and calling frames: A very long string could produce a StackOverflowError.
I suggest you take a look to standard method indexOf of java.lang.String:
A good alternative is Regular Expressions.
You can seperate the words considering comma ',' as delimeter
Code
String[] nextItem(String data) {
String[] words=data.split(",");
return words;
}
This will return an array of strings that is the words in your input string. Then you can use the array in anyway you need.
Hope it helps ;)
Processing comes with a split() function that does exactly what you're describing.
From the reference:
String men = "Chernenko,Andropov,Brezhnev";
String[] list = split(men, ',');
// list[0] is now "Chernenko", list[1] is "Andropov"...
Behind the scenes it's using the String#split() function like H. Sodi's answer, but you should just use this function instead of defining your own.
Using groovy how can I get the words/texts from a file which enclosed with parentheses.
Example:
George (a programmer) used to think much.
words to get: a programmer
Here you have an example program solving the issue:
String inp = 'George (a programmer) used to think much.'
def matcher = inp =~ /\(([^\)]+)\)/ // Try to find a match
if (matcher) { // Something found
String str = matcher[0][1] // Get the 1st capture group
printf("Found: %s.\n", str)
def words = str.tokenize() // Create a list of words
words.eachWithIndex{ it, i -> printf("%d: %s.\n", i, it)}
} else {
print("Not found")
}
Note the meaning of parentheses in the regular expression:
Outer (backslash quoted) parentheses are literal parentheses (we are
looking for these chars).
Unquoted parentheses (between them) are delimiters of the capture group.
The remaining (quoted) closing parenthesis between them is the char
that should not be present within the capture group.
So I was trying to make an asterisk pyramid using D.
First of all I noticed that concatenation seems to be impossible. Writing out something like writeln("foo" + "bar") will give you a syntax error. So instead I tried multiplying the strings like in python, that didn't work with double quoted strings, but with single quoted strings something weird happens.
If you type in this
import std.stdio;
void main()
{
foreach (i; 0 .. 10)
{
writeln(i*'0');
}
}
it will return a bunch of integers.
Could anyone explain why this happens?
And letting me know how to concatenate strings will also be really helpful.
thanks!
The '0' is not a string, it is a character, which uses ASCII encoding. The number is being multiplied with the encoding's integer id. For example, the encoding for ASCII's 'A' is 65.
import std.stdio;
int main()
{
writeln( cast(int)'A' );
writeln( 10 * 'A' );
return 0;
}
This program will print 65 and 650 because the character is being converted to an integer in both cases.
To solve the original concatenation problem you can use the '~' operator for concatenating two arrays, or use "array1 ~= array2" to append array2 onto array1 in one statement.
First solution that comes to mind:
char[5] arr3 = 's';
writeln(arr3);
Two alternatives are std.array.replicate and std.range.repeat:
import std.array;
import std.stdio;
void main() {
auto arr = replicate(['s'], 5); // lazy version: http://dlang.org/phobos/std_range.html#repeat
// or
auto arr2 = ['s'].replicate(5);
writeln(arr);
writeln(arr2);
}
Considering a search in a string for an exact match of another string. Is it safe to continue the search at the position where a partial match stopped to match, without getting wrong results?
In code:
int indexOf(string target, string search){
for(int i=0; i + search.length < target.length; i++){
int f=0;
for(; f < search.length && search[f] == target[i + f]; f++); //empty loop
if(f == search.length) return i;
i += f; //is it safe to do this without to worry about a missing match?
}
}
The thing to worry about is to miss an exact match starting in the partial match (somewhere between i and i + f in the code above). But in fact I couldn't think up any example case to proof the worry. Can you?
There are various string search algorithms here.
I think this is what you want which is know as KMP.
Yes, you need to worry about it, and an example of why you need to worry about it would be searching for the substring "ananas" in the string "anananas".
I am a novice programmer and I am trying to compare two characters from different strings, such that I can give an arbitrary index from each string and check to see if they match. From the processing website it seems that you can compare two strings, which I have done, but when I try to do so with characters it seems that the arguments (char,char) are not applicable. Can someone tell me where I am going wrong? Thanks.
You can use String's charAt() method/function to get character from each string at the desired index, then simply compare:
String s1 = ":)";
String s2 = ";)";
void setup(){
println(CompareCharAt(s1,s2,0));
println(CompareCharAt(s1,s2,1));
}
boolean CompareCharAt(String str1,String str2,int index){
return s1.charAt(index) == s2.charAt(index);
}
Note that when you're comparing strings == doesn't help, you need to use String's equal()
String s1 = ":)";
String s2 = ";)";
println(s1.equals(s2));
println(s1.equals(":)"));
Also, if data comes from external sources, it's usually a good idea to compare both strings at using the same case:
println("MyString".equals("myString"));
println("MyString".toLowerCase().equals("myString".toLowerCase()));
maybe you can pass the argument after converting(typecasting) the char to string.
(string(char),string(char))
Yep. Just use == as it gets interpreted as a char datatype.
This is assuming you've split the char from the String...
char a = 'a';
char b = 'a';
if(a == b) {
// etc
}
As mentioned above, use .equals() for String comparison.
String a = "a";
String b = "a";
if(a.equals(b)) {
// etc
}
Also, the proper way to cast a char as a String is str() not string()