How to align strings to right, and chop them if too long in Raku? - raku

The important part is, I want the alignment to hold, so the string gets chopped from left. I tried substr, but that crashes if a string is not long enough. Currently I have a similar solution to this:
> my $xs = (0..4).kv.map(-> $i, $x { ('a'..'z')[0..$i-1].join })
( a ab abc abcd)
> $xs.map({ sprintf '%3.3s', $_ }).raku
(" ", " a", " ab", "abc", "abc").Seq
But the problem is, the string still gets chopped from right, not left (chopping behaves as if aligned to left, not right). I am looking for something which would return:
(" ", " a", " ab", "abc", "bcd")
The difference is the last item where from "abcd" the "a" should be chopped, not the "d".

You could achieve that in a few different ways, but I'd probably break it down into two operations: ① take the last 3 characters (if any): .comb.tail(3).join; ② format the output with space-padding: .fmt("%3s").
Putting that in one line would replace your second line with:
> $xs.map({ .comb.tail(3).join.fmt("%3s")}).raku
(" ", " a", " ab", "abc", "bcd").Seq
Another alternative (which avoids the round-trip into a list) would be to add the padding first:
> $xs.map({.fmt("%3s").substr(*-3, *)}).raku
(" ", " a", " ab", "abc", "bcd").Seq
(Oh, and you didn't ask about this, but it would probably be more idiomatic Raku to save the list of strings into an #xs variable instead of an $xs one in many cases)

Not sure if flip is expensive, but:
$xs.map({$_.flip.substr(0,3).flip})
avoids the list, fmt, and the issue with substr.

Related

Building string from list of list of strings

I rather have this ugly way of building a string from a list as:
val input = listOf("[A,B]", "[C,D]")
val builder = StringBuilder()
builder.append("Serialized('IDs((")
for (pt in input) {
builder.append(pt[0] + " " + pt[1])
builder.append(", ")
}
builder.append("))')")
The problem is that it adds a comma after the last element and if I want to avoid that I need to add another if check in the loop for the last element.
I wonder if there is a more concise way of doing this in kotlin?
EDIT
End result should be something like:
Serialized('IDs((A B,C D))')
In Kotlin you can use joinToString for this kind of use case (it deals with inserting the separator only between elements).
It is very versatile because it allows to specify a transform function for each element (in addition to the more classic separator, prefix, postfix). This makes it equivalent to mapping all elements to strings and then joining them together, but in one single call.
If input really is a List<List<String>> like you mention in the title and you assume in your loop, you can use:
input.joinToString(
prefix = "Serialized('IDs((",
postfix = "))')",
separator = ", ",
) { (x, y) -> "$x $y" }
Note that the syntax with (x, y) is a destructuring syntax that automatically gets the first and second element of the lists inside your list (parentheses are important).
If your input is in fact a List<String> as in listOf("[A,B]", "[C,D]") that you wrote at the top of your code, you can instead use:
input.joinToString(
prefix = "Serialized('IDs((",
postfix = "))')",
separator = ", ",
) { it.removeSurrounding("[", "]").replace(",", " ") }
val input = listOf("[A,B]", "[C,D]")
val result =
"Serialized('IDs((" +
input.joinToString(",") { it.removeSurrounding("[", "]").replace(",", " ") } +
"))')"
println(result) // Output: Serialized('IDs((A B,C D))')
Kotlin provides an extension function [joinToString][1] (in Iterable) for this type of purpose.
input.joinToString(",", "Serialized('IDs((", "))')")
This will correctly add the separator.

Elm - mapping a list and appending string to the end of each item

I'm learning Elm and trying to understand how to append a string to all items in a list, but at the end of each entry rather than the beginning. Sorry for the n00b question but I've read through all the docs/examples around List.map, String (.append, .join) and can't seem to find an answer.
e.g.
--create username list
usernames = ["Dave", "Simon", "Sally", "Joe"]
--create confirmExit function
confirmExit name = String.append " has left the room" name
--apply confirmExit function to all items in username list
List.map (\x -> confirmExit x) usernames
Gives me:
["has leftDave","has leftSimon","has leftSally","has leftJoe"] : List String
But how would I make it so that it returned:
["Dave has left","Simon has left","Sally has left","Joe has left"] : List String
Is there an equivalent of .append to add to the end instead of the beginning? Please?!
You just have the parameters reversed, try:
confirmExit name = String.append name " has left the room"
From the docs:
append : String -> String -> String
Append two strings. You can also
use the (++) operator to do this.
append "butter" "fly" == "butterfly"
So you could also use:
confirmExit name = name ++ " has left the room"
Which is possibly a bit more readable

VBA MS Word conditional formatting

I have a VBA code that gives a value in a variable and then adds the variable in a document
Dim NoGFIs As Integer
NoGFIs = 1
ActiveDocument.Variables.Add Name:="GFIs ", Value:=NoGFIs
and I used a conditional statement in the word document
No of GFIs: {DOCVARIABLE GFIs}
Check IF: {IF <<GFIs>> = 1 "ONE" "NOT ONE"
But the outcome shows that something is wrong:
No of GFIs: 1
Check IF: NOT ONE
It shows that the GFIs value gets out from the VBA to the document, but IF fails to evaluate it??
Has anyone seen anything like that before?
Your if condition seems to be wrong. Please try the below:
{ IF { DOCVARIABLE GFIs \* MERGEFORMAT } = 1 "ONE" "NOT ONE"\* MERGEFORMAT }
Also, did you notice the trailing space in your variable name "GFIs " in ActiveDocument.Variables.Add Name:="GFIs ", Value:=NoGFIs?
Results:

Verify string does NOT contain a value other than known values [VB.NET]

I am trying to verify that a string contains nothing but known values. In this case, I need to make sure it contains only "Shift", "Control", or "Alt", but not necessarily all of those. For example, these should be true: "Shift + P", "Shift + Control + H", "Alt + U; but these should not: "Other + P", "Shift + Fake + Y", "Unknown + Shift + E" etc.
This is the code I tried to use:
If Not shortcut.Contains("Shift") Or Not shortcut.Contains("Control") Or Not shortcut.Contains("Alt") Then
MessageBox.Show("Invalid")
End If
I'm having difficulty wrapping my head around the needed logic to do this. I'm assuming there's a logic operator that can do this?
I believe you should not use strings for this purpose. You need a data type that can represent a hotkey combination, which is comprised of a "normal" key and a set of modifiers (Alt, Control, Shift), each of which can either be on or off. The on/off modifiers can be represented by an enum with flags, and the "normal" key can be represented by a separate enum. Both of the enums can be contained within a class.
The System.Windows.Forms.Keys enumeration can be used as both enums. You can store two numeric values (one for the modifiers, one for the "normal" key) - the underlying enum values - and they will represent the combination. No need to store strings.
If you do use strings for this purpose, you need to define your constraints better. Your rules do not specify how "Shift + Other" is invalid, but "Shift + F" is. A way to go about this, anyway, is to separate the string by " + " (assuming this is always the separator) and then compare each part to the list of valid values, which apparently contains "Shift", "Alt", "Control" and all single letters.
I think it would be easier to split the string into segments and then iterate through the list of words and then comparing to what words should exist. This is in C# but I guess you could figure it out.
C#:
string text = "Shift+Control+Alt+Other";
string[] textSegments = text.Split('+');
string[] allowedWords = { "Alt", "Shift", "Control" };
foreach (string t in textSegments)
{
bool temp = false;
foreach (string t2 in allowedWords)
{
if (t == t2)
{
temp = true;
continue;
}
}
if (!temp)
{
MessageBox.Show("Wrong!");
}
else
{
MessageBox.Show("Right!");
}
}
The output will be 4 MessageBoxes displaying: "Right!" "Right!" "Right!" "Wrong!"

Length Cannot be zero vb.net

Hi is there away to detect the length of a byte before I get the error message:
Length cannot be less than zero. Parameter name: length
I get the error on this line:
new_username = new_username.Substring(0, new_username.IndexOf(" Joined "))
I am removing the "joined" from the string I get....how can I ignore it is "joined" isnt the the data?
Thanks
I would test to see what IndexOf returned before using it in this context:
if(new_username.IndexOf(" Joined") > 0)
{
new_username = new_username.Substring(0, new_username.IndexOf(" Joined "))
}
Try this:
new_username = new_Username.Replace(" Joined ", "")
Be warned that this will remove all occurrences of the "Joined" substring rather than just the first.
It looks like new_username.IndexOf(" Joined ") is returning -1 meaning the string " Joined" was not found by Substring. I would break this out into two statements:
The error you are seeing is that you are effectively making this call:
new_username = new_username.Substring(0, -1)