c# string delimiter - c#-4.0

I have string value like this:
string strRole = "ab=Admin,ca=system,ou=application,role=branduk|ab=Manager,ca=system,ou=application,role=brankdusa|ab=sale,ca=system,ou=application,role=brandAu";
I just need to retrieve role to string array. I wonder if there is the best way to split the string in C# 4.0
string[] arrStrRole = strRole.Split('|').Select .. ??
Basically, I need brandUK, brandUsa, brandAu to string[] arrStrRole.
Thanks.

string[] arrStrRole = strRole.Split('|').Select(r => r.Split(new []{"role="}, StringSplitOptions.None)[1]).ToArray()
results in an string array with three strings:
branduk
brankdusa
brandAu

you can use string[] arrStrRole = strRole.Split('|',','); and this will split according to | and , characters

You can use String.Split in this LINQ query:
var roles = from token in strRole.Split('|')
from part in token.Split(',')
where part.Split('=')[0] == "role"
select part.Split('=')[1];
Note that this is yet prone to error and requires the data always to have this format. I mention it because you've started with Split('|').Select.... You can also use nested loops.
If you need it as String[] you just need to call ToArray:
String[] result = roles.ToArray();

I would go with Regex rather than splitting string. In combination with your intended Select solution, it could look like this:
var roles = Regex.Matches(strRole, #"role=(\w+)")
.Cast<Match>()
.Select(x => x.Groups[1].Value).ToArray();

You could use an extension like this which would allow you to test it easily.
public static string[] ParseRolesIntoList(this string csvGiven)
{
var list = new List<string>();
if (csvGiven == null) return null;
var csv = csvGiven.Split(',');
foreach (var s in csv)
{
if (string.IsNullOrEmpty(s)) continue;
if(!s.StartsWith("role")) continue;
var upperBound = s.IndexOf("|");
if (upperBound <= 0) upperBound = s.Length;
var role = s.Substring(s.IndexOf("=") + 1,
upperBound - s.IndexOf("=") - 1);
list.Add(role);
}
return list.ToArray();
}
Test below found brankdusa typo in your example. Some of the other answers would not deal with brandAu as it matches slightly differently. Try running this test against them if you like
[Test]
public void Should_parse_into_roles()
{
//GIVEN
const string strRole = "ab=Admin,ca=system,ou=application,role=branduk|ab=Manager,ca=system,ou=application,role=brankdusa|ab=sale,ca=system,ou=application,role=brandAu";
//WHEN
var roles = strRole.ParseRolesIntoList();
//THEN
Assert.That(roles.Length, Is.EqualTo(3));
Assert.That(roles[0], Is.EqualTo("branduk"));
Assert.That(roles[1], Is.EqualTo("brankdusa"));
Assert.That(roles[2], Is.EqualTo("brandAu"));
}

This gives an array of the 3 values.
void Main()
{
string strRole = "ab=Admin,ca=system,ou=application,role=branduk|ab=Manager,ca=system,ou=application,role=brankdusa|ab=sale,ca=system,ou=application,role=brandAu";
var arrStrRole = strRole.Split('|',',')
.Where(a => a.Split('=')[0] == "role")
.Select(b => b.Split('=')[1]);
arrStrRole.Dump();
}

Related

Generic Template String like in Python in Dart

In python, I often use strings as templates, e.g.
templateUrl = '{host}/api/v3/{container}/{resourceid}'
params = {'host': 'www.api.com', 'container': 'books', 'resourceid': 10}
api.get(templateUrl.format(**params))
This allows for easy base class setup and the like. How can I do the same in dart?
I'm assuming I will need to create a utility function to parse the template and substitute manually but really hoping there is something ready to use.
Perhaps a TemplateString class with a format method that takes a Map of name/value pairs to substitute into the string.
Note: the objective is to have a generic "format" or "interpolation" function that doesn't need to know in advance what tags or names will exist in the template.
Further clarification: the templates themselves are not resolved when they are set up. Specifically, the template is defined in one place in the code and then used in many other places.
Dart does not have a generic template string functionality that would allow you to insert values into your template at runtime.
Dart only allows you to interpolate strings with variables using the $ syntax in strings, e.g. var string = '$domain/api/v3/${actions.get}'. You would need to have all the variables defined in your code beforehand.
However, you can easily create your own implementation.
Implementation
You pretty much explained how to do it in your question yourself: you pass a map and use it to have generic access to the parameters using the [] operator.
To convert the template string into something that is easy to access, I would simply create another List containing fixed components, like /api/v3/ and another Map that holds generic components with their name and their position in the template string.
class TemplateString {
final List<String> fixedComponents;
final Map<int, String> genericComponents;
int totalComponents;
TemplateString(String template)
: fixedComponents = <String>[],
genericComponents = <int, String>{},
totalComponents = 0 {
final List<String> components = template.split('{');
for (String component in components) {
if (component == '') continue; // If the template starts with "{", skip the first element.
final split = component.split('}');
if (split.length != 1) {
// The condition allows for template strings without parameters.
genericComponents[totalComponents] = split.first;
totalComponents++;
}
if (split.last != '') {
fixedComponents.add(split.last);
totalComponents++;
}
}
}
String format(Map<String, dynamic> params) {
String result = '';
int fixedComponent = 0;
for (int i = 0; i < totalComponents; i++) {
if (genericComponents.containsKey(i)) {
result += '${params[genericComponents[i]]}';
continue;
}
result += fixedComponents[fixedComponent++];
}
return result;
}
}
Here would be an example usage, I hope that the result is what you expected:
main() {
final templateUrl = TemplateString('{host}/api/v3/{container}/{resourceid}');
final params = <String, dynamic>{'host': 'www.api.com', 'container': 'books', 'resourceid': 10};
print(templateUrl.format(params)); // www.api.com/api/v3/books/10
}
Here it is as a Gist.
Here is my solution:
extension StringFormating on String {
String format(List<String> values) {
int index = 0;
return replaceAllMapped(new RegExp(r'{.*?}'), (_) {
final value = values[index];
index++;
return value;
});
}
String formatWithMap(Map<String, String> mappedValues) {
return replaceAllMapped(new RegExp(r'{(.*?)}'), (match) {
final mapped = mappedValues[match[1]];
if (mapped == null)
throw ArgumentError(
'$mappedValues does not contain the key "${match[1]}"');
return mapped;
});
}
}
This gives you a very similar functionality to what python offers:
"Test {} with {}!".format(["it", "foo"]);
"Test {a} with {b}!".formatWithMap({"a": "it", "b": "foo"})
both return "Test it with foo!"
It's even more easy in Dart. Sample code below :
String host = "www.api.com"
String container = "books"
int resourceId = 10
String templateUrl = "$host/api/v3/$container/${resourceId.toString()}"
With the map, you can do as follows :
Map<String, String> params = {'host': 'www.api.com', 'container': 'books', 'resourceid': 10}
String templateUrl = "${params['host']}/api/v3/${params['container']}/${params['resourceId']}"
Note : The above code defines Map as <String, String>. You might want <String, Dynamic> (and use .toString())
Wouldn't it be simplest to just make it a function with named arguments? You could add some input validation if you wanted to.
String templateUrl({String host = "", String container = "", int resourceid = 0 }) {
return "$host/api/v3/$container/$resourceId";
}
void main() {
api.get(templateUrl(host:"www.api.com", container:"books", resourceid:10));
}

String comparison not working for sharepoint multiline text values

I am fetching data from sharepoint list for a multi line column.
And then split the data by space and comparing it to other string but despite the value in both the strings being same it gives false result.
Please follow the below code:
string[] strBodys = SPHttpUtility.ConvertSimpleHtmlToText(Convert.ToString(workflowProperties.ListItem[SCMSConstants.lstfldBody]), Convert.ToString(workflowProperties.ListItem[SCMSConstants.lstfldBody]).Length).Split(' ');
bool hasKwrdInBody = false;
foreach (SPItem oItem in oColl)
{//get all the keywords
string[] strkeyWrds = SPHttpUtility.ConvertSimpleHtmlToText(Convert.ToString(oItem[SCMSConstants.lstfldKWConfigKeywordsIntrName]), Convert.ToString(oItem[SCMSConstants.lstfldKWConfigKeywordsIntrName]).Length).Split(',');
//in body
foreach (string strKW in strkeyWrds)
{
string KWValue = strKW.Trim(' ').ToLower();
foreach (string strBdy in strBodys)
{
string BodyValue = strBdy.Trim(' ').ToLower();
//if (strKW.ToLower().Equals(strBdy.ToLower()))
if(KWValue == BodyValue) //here it always gives false result
{
hasKwrdInBody = true;
break;
}
}
if (hasKwrdInBody)
break;
}
if (!hasKwrdInSbjct && !hasKwrdInBody)
{
continue;
}
else
{
//set business unit to current groups rule
bsnsUnitLookupFld = new SPFieldLookupValue(Convert.ToString(oItem[SCMSConstants.lstfldBsnsUnit]));
asgndTo = new SPFieldUserValue(objWeb,Convert.ToString(oItem[SCMSConstants.lstfldKWConfigAssignedToIntrName])).User;
groupName = Convert.ToString(oItem[SCMSConstants.lstfldKWConfigAssignedToGroupIntrName]).Split('#').Last();
break;
}
}
Please mind that i am trying to get multi line text from sharepoint list
Please provide your suggestions.
That also depends on the exact type of your Multiline field (e.g Plain Text or RichText, etc.).
Maybe it would be clear if you just added some logging writing out the values you are comparing.
For details on how to get the value of a Multiline textfield check Accessing Multiple line of text programmatically
and here for RichText
I got it working by comparing and counting the characters in both the strings. Actually some UTC codes were embedded in to the string. First I removed those characters using regular expression and then compared them and it worked like a charm.
Here is the code snippet, might help some one.
string[] strBodys = SPHttpUtility.ConvertSimpleHtmlToText(Convert.ToString(workflowProperties.ListItem[SCMSConstants.lstfldBody]), Convert.ToString(workflowProperties.ListItem[SCMSConstants.lstfldBody]).Length).Split(' ');
bool hasKwrdInBody = false;
foreach (SPItem oItem in oColl)
{//get all the keywords
string[] strkeyWrds = SPHttpUtility.ConvertSimpleHtmlToText(Convert.ToString(oItem[SCMSConstants.lstfldKWConfigKeywordsIntrName]), Convert.ToString(oItem[SCMSConstants.lstfldKWConfigKeywordsIntrName]).Length).Split(',');
//in body
foreach (string strKW in strkeyWrds)
{
string KWValue = strKW.Trim(' ').ToLower();
KWValue = Regex.Replace(KWValue, #"[^\u0000-\u007F]", string.Empty); //here replaced the utc codes
foreach (string strBdy in strBodys)
{
string BodyValue = strBdy.Trim(' ').ToLower();
BodyValue = Regex.Replace(BodyValue, #"\t|\n|\r", string.Empty); // new code to replace utc code
BodyValue = Regex.Replace(BodyValue, #"[^\u0000-\u007F]", string.Empty); //new code to replace utc code
//if (strKW.ToLower().Equals(strBdy.ToLower()))
if(KWValue == BodyValue) //here it always gives false result
{
hasKwrdInBody = true;
break;
}
}
if (hasKwrdInBody)
break;
}
if (!hasKwrdInSbjct && !hasKwrdInBody)
{
continue;
}
else
{
//set business unit to current groups rule
bsnsUnitLookupFld = new SPFieldLookupValue(Convert.ToString(oItem[SCMSConstants.lstfldBsnsUnit]));
asgndTo = new SPFieldUserValue(objWeb,Convert.ToString(oItem[SCMSConstants.lstfldKWConfigAssignedToIntrName])).User;
groupName = Convert.ToString(oItem[SCMSConstants.lstfldKWConfigAssignedToGroupIntrName]).Split('#').Last();
break;
}
}

Random string in AS3

I have recently worked on AS3 project with a module that works like this:
I have 50 strings and I am picking one randomly of them at a given time. When I am done with the picked one I choose another one of the 49 left again randomly and so on.
I managed to solve this problem using helper arrays, for cycles, mapping index numbers with the strings. Although every thing works just fine I found my code very messed and hard to understand.
Is there a much more easy and cleaner way to solve this problem in AS3?
Maybe there is a library for getting random string out of strings?
Something simple like this class:
public class StringList
{
private var _items:Array = [];
public function StringList(items:Array)
{
_items = items.slice();
}
public function get random():String
{
var index:int = Math.random() * _items.length;
return _items.splice(index, 1);
}
public function get remaining():int{ return _items.length; }
}
And its usage:
var list:StringList = new StringList(['a', 'b', 'c', 'd']);
while(list.remaining > 0)
{
trace(list.random);
}
I'm not sure what do you want to do with that procedure, but here's one proposal:
var stringArray:Array = new Array("string1", "string2", "string2"); //your array with strings
var xlen:uint = stringArray.length-1; //we get number of iterations
for (var x:int = xlen; x >= 0; x--){ //we iterate backwards
var randomKey:Number = Math.floor(Math.random()*stringArray.length); //gives you whole numbers from 0 to (number of items in array - 1)
stringArray.splice(randomKey,1); //remove item from array with randomKey index key
var str:String = stringArray[randomKey]; //output item into new string variable or do whatever
}

Converting Guid to Cassandra UUID

I want to convert a Guid to a UUID or a string version of the same so that the following CQL query will work.
if (cassandraDb.ExecuteQuery(string.Format("SELECT OrderGroupId FROM Order WHERE OrderGroupId={0}", orderGroupId)).Count() <= 0) {
The variable 'orderGroupId' is a Guid. Obviously this is using FluentCassandra in a C#/.NET environmnet. Any hints?
Thank you.
To convert System.Guid to FluentCassandra.Types.UUIDType you just need to assign one into the other.
Same goes for FluentCassandra.Types.TimeUUIDType.
Execute the CQL query directly as a string by using the .ToString() property.
string.Format("SELECT OrderGroupId FROM Order WHERE OrderGroupId={0}", orderGroupId.ToString())
Should work fine. If it does not... you may want to try this (which I found on a comment thread on one of the C# clients):
protected static string ToCqlString(Guid guid) {
var bytes = guid.ToByteArray();
StringBuilder sb = new StringBuilder(bytes.Length * 2);
for (int i = 0; i < 16; i++) {
if (i == 4 || i == 6 || i == 8 || i == 10) {
sb.Append("-");
}
var b = bytes[i];
sb.AppendFormat("{0:x2}", b);
}
return sb.ToString();
}
Cheers,
Allison

Lines of a StreamReader to an array of string

I want to get a string[] assigned with a StreamReader. Like:
try{
StreamReader sr = new StreamReader("a.txt");
do{
str[i] = sr.ReadLine();
i++;
}while(i < 78);
}
catch (Exception ex){
MessageBox.Show(ex.ToString());
}
I can do it but can't use the string[]. I want to do this:
MessageBox.Show(str[4]);
If you need further information feel free to ask, I will update.
thanks in advance...
If you really want a string array, I would approach this slightly differently. Assuming you have no idea how many lines are going to be in your file (I'm ignoring your hard-coded value of 78 lines), you can't create a string[] of the correct size up front.
Instead, you could start with a collection of strings:
var list = new List<string>();
Change your loop to:
using (var sr = new StreamReader("a.txt"))
{
string line;
while ((line = sr.ReadLine()) != null)
{
list.Add(line);
}
}
And then ask for a string array from your list:
string[] result = list.ToArray();
Update
Inspired by Cuong's answer, you can definitely shorten this up. I had forgotten about this gem on the File class:
string[] result = File.ReadAllLines("a.txt");
What File.ReadAllLines does under the hood is actually identical to the code I provided above, except Microsoft uses an ArrayList instead of a List<string>, and at the end they return a string[] array via return (string[]) list.ToArray(typeof(string));.

Resources