String t_liv="[http://X.X.X.X.X/trac/livraisons_t24/ticket/38068 38068]-[http://X.X.X.X.X/trac/livraisons_t24/ticket/38168 38168]-[http://X.X.X.X.X/trac/livraisons_t24/ticket/39312 39312]"
any solution to convert this String to array String with this format
[38068,38168,39312]
https://www.tutorialspoint.com/java/java_string_split.htm
split() will split a string into a string array depending on its parameter which is a regex that will act as your condition.
this my solution :
String t_liv="[http://X.X.X.X.X/trac/livraisons_t24/ticket/38068 38068]-[http://X.X.X.X.X/trac/livraisons_t24/ticket/38168 38168]-[http://X.X.X.X.X/trac/livraisons_t24/ticket/39312 39312]"
public ArrayList<String> getAllIds(String t_liv) {
ArrayList<String> arrayids = new ArrayList<String>();
if(t_liv!=null)
{
String[] ids=t_liv.split("-");
for(String p: ids)
{
String resultp= p.substring(p.length()-6);
String resultfinal=resultp.substring(0,5);
System.out.println(resultfinal);
arrayids.add(resultfinal);
}
}
return arrayids;
}
Related
I'm just learning visual c# in visual studio
Ok, so I have a ton of data fields in a form, and then I want to write the handlers to all call one main method, update, which then updates a resultsEntry object, which encapsulates a bunch of uint variables with various names.
How do I write an update method to put in either the results object, or the update method that will take the name of the variable in resultsEntry as a string, and the integer to update it with, and then update that field.
Basically, I need to do a
resultsEntry.(inStringHere) = inValueHere;
where resultsEntry is the object being updated, the inStringHere specifies the field to be updated, and the inValueHere represents the integer value to assign to it.
Thanks!
Sam French
You have two challenges,
Setting a field/property in class using a string (the focus of your question). This will be accomplished using reflection.
Converting values to the type in your class (this may not be a problem for you, you may have 'typed' values. I have an ugly solution because this is not the main focus of your question.
Setting a property by name (see comments preceded with '**'):
static class Program
{
// A 'ResultEntry' type
public class ResultEntry
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
static void Main()
{
// some tuples Field1 = Property Name; Field2 = Raw Value (string)
List<Tuple<string, string>> rawEntries = new List<Tuple<string, string>>() {
new Tuple<string,string>("ID", "1")
, new Tuple<string, string>("FirstName", "George")
, new Tuple<string, string>("LastName", "Washington")
};
ResultEntry resultEntry = new ResultEntry();
// ** Get MemberInfo's for your ResultEntry. Do this once, not for each instance of ResultEntry!
MemberInfo[] members = resultEntry.GetType().GetMembers(BindingFlags.Public | BindingFlags.Instance);
// Iterate over input
foreach (var raw in rawEntries)
{
// find a MemberInfo (PropertyInfo) that matches your input 'PropertyName'
MemberInfo member = members.FirstOrDefault(m => m.MemberType == MemberTypes.Property && m.Name == raw.Item1);
if (member != null)
{
// if you input is typed you will not have to deal with
// conversion of the string to the actual type of the property
object val = raw.Item2.MyConverter(((PropertyInfo)member).PropertyType);
// ** set the value in 'ResultEntry'
((PropertyInfo)member).SetValue(resultEntry, val, null);
}
}
Console.WriteLine(string.Format("Result Entry: ID = {0}, FirstName = {1}, LastName = {2}", resultEntry.ID, resultEntry.FirstName, resultEntry.LastName));
Console.ReadLine();
}
}
If you need to deal with converting raw string input to type (e.g. string to int), then is just one strategy...
public static class Extensions
{
public static object MyConverter(this string rawValue, Type convertToMe)
{
// ugly, there are other strategies
object val;
if (convertToMe == typeof(Int32))
val = Convert.ToInt32(rawValue);
// ... add other type conversions
else
val = rawValue;
return val;
}
}
Hope this helps.
I'm trying to find a string from the List....seems like its not working and if I have just List<string> it does work.. meaning like the below code...
List<string> c = new List<string>();
c.Add("John Doe"));
c.Add("Erich Schulz"));
//I think the problem with the Criterion class?
here is my class structure:
public class Criterion
{
public Criterion(String propertyName, object value)
{
this.PropertyName = propertyName;
this.Value = value;
}
}
//here is the method...
public static List<Criterion> LoadNames()
{
List<Criterion> c = new List<Criterion>();
c.Add(new Criterion("Name1", "John Doe"));
c.Add(new Criterion("Name2", "Erich Schulz"));
return c;
}
here is the code I'm trying to make it work:
bool isExists = LoadNames.Any(s=> "Erich Schulz".Contains(s));
Error:
does not contain a definition for 'Any' and the best extension method overload 'System.Linq.Enumerable.Any<TSource>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,bool>)' has some invalid arguments
When you call .Contains(s), s isn't a string, it's Criterion. Use .Contains(s.propertyName).
bool isExists = LoadNames().Any(s=> "Erich Schulz".Contains(s.PropertyName));
Also you're using LoadNames as a method, you need to execute it first.
You're attempting to compare a string to a Criterion object, which just doesn't work.
Here is the fixed code:
bool isExists = LoadNames.Any(criterion => String.Equals(criterion.PropertyName, "Erich Schulz", StringComparison.OrdinalIgnoreCase));
Hello MVC and LINQ Experts,
I have a Model that looks like this:
public class SomeClass : IValidatableObject
{
public string SomeString { get; set; }
public string SomeString2 { get; set; }
public int SomeInteger { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
//... IF there is some error...THEN
yield return new ValidationResult("Some Error Message.", GetFieldNames(() => new []{ this.SomeString }));
}
}
As you can see, I am calling GetFieldNames that takes an expression, and returns to you the expression members as a string array. According to a book I read recently, the way to link an error to a field is to pass it as a string as follows:
yield return new ValidationResult("Some Error Message.", new []{ "SomeString" }));
But I wanted to be Strongly Typed, so here is the method that I wrote:
public static string[] GetFieldNames(Expression<Func<object[]>> exp)
{
//Build a string that will in the end look like this: field1,field2,field3
//Then we split(',') it into an array and return that string array.
string fieldnames = "";
MemberExpression body = exp.Body as MemberExpression;
if (body == null)
{
NewArrayExpression ubody = (NewArrayExpression)exp.Body;
foreach(MemberExpression exp2 in ubody.Expressions)
{
fieldnames += exp2.Member.Name + ",";
}
fieldnames = fieldnames.TrimEnd(',');
}
if(fieldnames.Length > 0)
return fieldnames.Split(',');
else
return new string[]{};
}
Current Usage:
GetFieldNames(() => new[] { this.SomeString , this.SomeString2 });
Output:
{ "SomeString" , "SomeString2" }
This works fine.
The problem is that if I use it as follows, it gives me an error (compile time):
GetFieldNames(() => new[] { this.SomeString , this.SomeInteger });
Error:
No best type found for implicitly-typed array
My Desired Output:
{ "SomeString" , "SomeInteger" }
I can't pass in an array of object because int is not a complex type.
How can I pass the function an expression array with int and string?
You could try passing an array of objects (which is what your expression expects) instead of trying to use an array initializer syntax:
GetFieldNames(() => new object[] { this.SomeString, this.SomeInteger });
This allows you to pass arbitrary object types.
You could define an interface IFieldName that enables usage in your list, and then implement it in different classes (int, error, string, etc.) for the actual types that occur in your processing.
This is roughly equivalent to defining an rray of object, but restores type-safety.
With the help of Darin Dimitri (the idea to pass a new object[] instead of new []
The following code will make sure that your IValidatableObject can now be strongly typed instead of just an array of strings.
public static string[] GetFieldNames(Expression<Func<object[]>> exp)
{
string fieldnames = "";
MemberExpression body = exp.Body as MemberExpression;
if (body == null)
{
NewArrayExpression ubody = (NewArrayExpression)exp.Body;
foreach (Expression exp2 in ubody.Expressions)
{
if (exp2 is MemberExpression) {
fieldnames += ((MemberExpression)exp2).Member.Name + ",";
}
else {
var op = ((UnaryExpression)exp2).Operand;
fieldnames += ((MemberExpression)op).Member.Name + ",";
}
}
fieldnames = fieldnames.TrimEnd(',');
}
if(fieldnames.Length > 0)
return fieldnames.Split(',');
else
return new string[]{};
}
Usage:
GetFieldNames(() => new object[] { this.SomeString, this.SomeInteger }));
Usage for MVC Validation:
yield return new ValidationResult("Some Error.", GetFieldNames(() => new object[] { this.SomeString, this.SomeInteger }));
If I have following type hierarchy:
abstract class TicketBase
{
public DateTime PublishedDate { get; set; }
}
class TicketTypeA:TicketBase
{
public string PropertyA { get; set; }
}
class TicketTypeB:TicketBase
{
public string PropertyB { get; set; }
}
and many more TicketTypes : TicketBase
and want to create a function which selects any property e.g. PropertyA from any ticket type e.g. TicketTypeA
I wrote this function:
private Func<TicketBase, String> CreateSelect(Type t, String FieldName)
{
var parameterExp = Expression.Parameter(t, "sel");
var fieldProp = Expression.PropertyOrField(parameterExp, FieldName);
var lambda = Expression.Lambda<Func<TicketBase, String>>(fieldProp, parameterExp);
return lambda.Compile();
}
and call it on a List<TicketBase> Tickets like so:
Type typeToSelectFrom = typeof(TicketTypeA);
String propertyToSelect = "PropertyA";
Tickets.Select(CreateSelect(typeToSelectFrom, propertyToSelect));
I get the following ArgumentException:
ParameterExpression of type 'TicketTypes.TicketTypeA' cannot be used for delegate parameter of type 'Types.TicketBase'
Anyone know how to fix this?
Well, one option is to include a cast, e.g.
private Func<TicketBase, String> CreateSelect(Type t, String FieldName)
{
var parameterExp = Expression.Parameter(typeof(TicketBase), "sel");
var cast = Expression.Convert(parameterExp, t);
var fieldProp = Expression.PropertyOrField(cast, FieldName);
var lambda = Expression.Lambda<Func<TicketBase, String>>(fieldProp,
parameterExp);
return lambda.Compile();
}
So that calling CreateSelect(typeof(TicketTypeA), "PropertyA") is equivalent to:
Func<TicketBase, string> func = tb => ((TicketTypeA)tb).PropertyA;
Obviously that's going to fail if you apply it to a TicketBase value which refers to (say) a TicketTypeB, but it's hard to avoid that, if you've got a List<TicketBase> or something similar.
I have an array of input strings that contains either email addresses or account names in the form of domain\account. I would like to build a List of string that contains only email addresses. If an element in the input array is of the form domain\account, I will perform a lookup in the dictionary. If the key is found in the dictionary, that value is the email address. If not found, that won't get added to the result list. The code below will makes the above description clear:
private bool where(string input, Dictionary<string, string> dict)
{
if (input.Contains("#"))
{
return true;
}
else
{
try
{
string value = dict[input];
return true;
}
catch (KeyNotFoundException)
{
return false;
}
}
}
private string select(string input, Dictionary<string, string> dict)
{
if (input.Contains("#"))
{
return input;
}
else
{
try
{
string value = dict[input];
return value;
}
catch (KeyNotFoundException)
{
return null;
}
}
}
public void run()
{
Dictionary<string, string> dict = new Dictionary<string, string>()
{
{ "gmail\\nameless", "nameless#gmail.com"}
};
string[] s = { "anonymous#gmail.com", "gmail\\nameless", "gmail\\unknown" };
var q = s.Where(p => where(p, dict)).Select(p => select(p, dict));
List<string> resultList = q.ToList<string>();
}
While the above code works (hope I don't have any typo here), there are 2 problems that I do not like with the above:
The code in where() and select() seems to be redundant/repeating.
It takes 2 passes. The second pass converts from the query expression to List.
So I would like to add to the List resultList directly in the where() method. It seems like I should be able to do so. Here's the code:
private bool where(string input, Dictionary<string, string> dict, List<string> resultList)
{
if (input.Contains("#"))
{
resultList.Add(input); //note the difference from above
return true;
}
else
{
try
{
string value = dict[input];
resultList.Add(value); //note the difference from above
return true;
}
catch (KeyNotFoundException)
{
return false;
}
}
}
The my LINQ expression can be nicely in 1 single statement:
List<string> resultList = new List<string>();
s.Where(p => where(p, dict, resultList));
Or
var q = s.Where(p => where(p, dict, resultList)); //do nothing with q afterward
Which seems like perfect and legal C# LINQ. The result: sometime it works and sometime it doesn't. So why doesn't my code work reliably and how can I make it do so?
If you reverse the where and the select you can convert unknown domain accounts to null first, then just filter them out.
private string select(string input, Dictionary<string, string> dict)
{
if (input.Contains("#"))
{
return input;
}
else
{
if (dict.ContainsKey(input))
return dict[input];
}
return null;
}
var resultList = s
.Select(p => select(p, dict))
.Where(p => p != null)
.ToList()
This takes care of your duplicate code.
It takes 2 passes. The second pass converts from the query expression to List.
Actually this is only one pass as LINQ is lazy evaluated. This is why your last statements only work sometimes. The filter is only applied and your list generated if the LINQ query is evaluated. Otherwise the Where statement is never run.
It sounds like what you want is an iterator. By making your own iterator you can filter the list and produce output at the same time.
public static IEnumerable EmailAddresses(IEnumerable<string> inputList,
Dictionary<string, string> dict)
{
foreach (string input in inputList)
{
string dictValue;
if (input.Contains("#"))
yield return input;
else if (TryGetValue(input, out dictValue)
yield return dictValue;
// else do nothing
}
}
List<string> resultList = EmailAddresses(s, dict).ToList();
You don't generally want to have side-effects on an unrelated object like your list. It makes it difficult to understand, debug, and refactor. I wouldn't worry about optimizing the query until you know it's not performing well.
So, what's wrong with your original expression? You don't need both the select and the where. You only need the Where() call. This will return a list of email addresses, which you can stick into a HashSet. The HashSet will provide the uniqueness you seem to desire. This will add execution time, so if you don't need it, don't use it.
You should only really need something like:
var s = new[] {"me#me.com", "me_not_at_me.com", "not_me"};
var emailAddrs = s.Where( a => a.Contains("#")); // This is a bad email address validator; find a better one.
var uniqueAddrs = new HashSet<string>(emailAddrs);
(Note, I've not dealt with HashSet, so the constructor might not take an Enumerable. This would be an exercise for the reader.)
Here is one way you could approach it with LINQ. It groups the values by whether or not they are email addresses, resulting in 2 groups of strings. If a group is the email address group, we select directly from it, otherwise we look up the emails and select from those:
public static IEnumerable<string> SelectEmails(
this IEnumerable<string> values,
IDictionary<string, string> accountEmails)
{
return
from value in values
group value by value.Contains("#") into valueGroup
from email in (valueGroup.Key ? valueGroup : GetEmails(valueGroup, accountEmails))
select email;
}
private static IEnumerable<string> GetEmails(
IEnumerable<string> accounts,
IDictionary<string, string> accountEmails)
{
return
from account in accounts
where accountEmails.ContainsKey(account)
select accountEmails[account];
}
You would use it like this:
var values = new string[] { ... };
var accountEmails = new Dictionary<string, string> { ... };
var emails = values.SelectEmails(accountEmails).ToList();
Of course, the most straightforward way to implement this extension method would be #gabe's approach.