Using linq with string split - c#

workareaRefs is a string of random values splitted by comma i.e. 4,7,1,7 etc.
I am setting properties to TrackDataFilter and would like to set the Workareas
which is of type IList with the values in workareaRefs var.
So Workareas should contain the values in workareaRefs stored in the variable named r.
Can anyone help me achieve this?
var workareasRefs = workareaRefs.Split(',');
var r = new TrackDataFilter
{
DatePreset = preset,
Workareas = new List<TrackFilterGenericRef>
{
new TrackFilterGenericRef
{
Ref = 2, Type = Enums.ContentTypes.Workarea
}
},
};

Well, I am not sure If I understand your question correctly, so by guessing a bit, I would assume you want to do the following
WorkAreas = new List(workareasRefs);

Related

How to send multi-select attribute values to Acumatica

I can't find an example of this here or in the Acumatica sample code. Sending single attribute values works fine, but I can't find a way to send multi-select ones. They are returned as a comma-separated list in a string value, but sending them that way doesn't work. Also, sending them as multiple instances of single values doesn't work.
Here's what I've tried. (In the actual code I'm sending some other single attributes in the list, as well, but those work fine.)
// this results in nothing being set for the attribute
string interestedIn = "Brochure, Contact, Collecting small stones";
List<Acumatica.AttributeDetail> attributes = new List<Acumatica.AttributeDetail>();
attributes.Add(
new Acumatica.AttributeDetail {
Attribute = new Acumatica.StringValue { Value = "Interested in" },
Value = new Acumatica.StringValue { Value = interestIn }
}
);
custAdd.Attributes = attributes.ToArray();
// this results in the last item in the list being set for the attribute
string interestedIn = "Brochure, Contact, Collecting small stones";
List<Acumatica.AttributeDetail> attributes = new List<Acumatica.AttributeDetail>();
string[] interests = Convert.ToString(interestedIn).Split(',');
foreach (string interest in interests) {
attributes.Add(
new Acumatica.AttributeDetail {
Attribute = new Acumatica.StringValue { Value = "Interested in" },
Value = new Acumatica.StringValue { Value = interest.Trim() }
}
);
};
custAdd.Attributes = attributes.ToArray();
From the source
MappedCustomer obj = bucket.Customer;
Core.API.Customer impl = obj.Local;
impl.Attributes = impl.Attributes ?? new List<AttributeValue>();
AttributeValue attribute = new AttributeValue();
attribute.AttributeID = new StringValue() { Value = attributeID };
attribute.ValueDescription = new StringValue() { Value = attributeValue?.ToString() };
impl.Attributes.Add(attribute);
Some subtle differences here. Also, I wonder if the .ToArray() call is necessary.

Simple way to split and joiin a string with Object Initializer?

Is there a way to shorten this code below. (expecting 20+ values)
The values will always remain in the same order.
string[] values = line.Split(',');
LogEntry entry = new LogEntry()
{
Id = values[0],
Service = values[1],
Name = values[2],
Process = values[3],
type = values[4]
[...]
};
I personally do not know of a simplified way of doing this -- somewhere this code would need to exist. However, you could use a mapper solution like AutoMapper to set up a mapping. At least this your handlers or actions aren't bloated with assignment logic.
Hope this helps a bit.
Looking forward to reading other answers.
You can add to LogEntry constructor with one param string line and move logic into constructor.
Then code will be look like
LogEntry entry = new LogEntry(line);
And in constructor something like this:
public void LogEntry(string line)
{
string[] values = line.Split(',');
Id = values[0],
Service = values[1],
Name = values[2],
Process = values[3],
type = values[4]
[...]
}
This code must be somewhere.
Is it better solution depends on the situation. If you often used the object initializer that will greatly simplify the code. If you do not it's probably not have much of a difference.
From your question, you are trying to avoid those twenty lines of setting the values. How about using a reflection based solution like the one below ?
string[] values = line.Split(',');
var orderedLogEntryPropertyNames =
new string[]{ "Id", "Name", "Process" };
//list all the LogEntry property names in the order that map to the values
var logEntry = new LogEntry();
var logEntryProperties = typeof(LogEntry).GetProperties();
for (int i = 0; i < values.Length; i++)
{
var propertyToSet =
logEntryProperties.First(p => p.Name.Equals(orderedLogEntryPropertyNames[i]));
propertyToSet.SetValue(logEntry, values[i]);
}

Querying a list of strings with a query string?

I have a dictionary:
<string,List<string>>
The key is the product code say "product1" then the list is a list of properties:
"Brand","10.40","64","red","S"
Then I 'can' have a list of rules/filters e.g.
var tmpFilter = new customfilters();
tmpFilter.Field = "2";
tmpFilter.Expression = ">";
tmpFilter.Filter = "10";
So for the above example this would pass because at index 2 (tmpFilter.Field) it is more than 10; then I have another object which defines which fields within the list I want to write to file. For that dictionary item I just want to write the product brand and price where the filters match.
At the moment without the filter I have:
var tmp = new custom();
tmp.Columns = "0,1";
tmp.Delimiter = ",";
tmp.Extention = ".csv";
tmp.CustomFilters = new List<customfilters>() {new customfilters(){ Field = "2", Expression = ">", Filter = "10"} };
public static void Custom(custom custom)
{
foreach (var x in Settings.Prods)
{
//Get Current Product Code
var curprod = Settings.ProductInformation[x];// the dictionary value
foreach (var column in custom.Columns)
{
var curVal = curprod[Convert.ToInt32(column)];
tsw.Write(curVal + custom.Delimiter);
}
Settings.Lines++;
tsw.WriteLine();
}
tsw.Close();
}
I only want to write the curprod if all the filters pass for that list of strings.
How I can do this?
There's a really nice Nuget package based on an example published by Microsoft, that they have decided to make really hard to find for some reason, that allows dynamic linq queries:
https://www.nuget.org/packages/System.Linq.Dynamic/1.0.2
Source:
https://github.com/kahanu/System.Linq.Dynamic
Using that you can do stuff like this very easily (note: I used strings here because the OP states they have a List<string>):
List<string> stuff = new List<string> { "10.40", "64", "5", "56", "99", "2" };
var selected = stuff.Select(s => new { d = double.Parse(s) }).Where("d > 10");
Console.WriteLine(string.Join(", ", selected.Select(s => s.d.ToString()).ToArray()));
Outputs:
10.4, 64, 56, 99
That may give you a place to start. One thing you are going to have to tackle is identifying which of your fields are numeric and should be converted to a numeric type before trying to apply your filter. Otherwise you are going to comparing as strings.

Assigning properties to an object

Okay so I have a small section of code which creates a list of objects based on the data model. I don't want to have to create a class for this. It is used on n ASP.net MVC application for populating a user notifications list.
I know there are plenty of other ways to do this such as actually setting up a class for it(probably the easiest method), but I would like to know if there is a way to do what is displayed below.
List<object> notificationList = new List<object>();
object userNotification = new { Text = "Here is some text!", Url = "http://www.google.com/#q=notifications" };
notificationList.Add(userNotification);
foreach(object notification in notificationList)
{
string value = notification.Text;
}
So I haven't populated the list much but for the purposes here you get the idea. After debug I notice that the Text and Url properties exist, however cannot code to get the values???
You need to use dynamic as variable type in the foreach:
foreach(dynamic notification in notificationList)
{
string value = notification.Text;
}
Edit Oops ... you do need "dynamic", either as the List's generic type, or in the foreach.
var notificationList = new List<dynamic>();
var userNotification = new { Text = "Here is some text!", Url = "http://www.google.com/#q=notifications" };
notificationList.Add(userNotification);
foreach (var notification in notificationList)
{
string value = notification.Text;
}
End edit
Anonymous types should be declared using the var keyword:
var userNotification = new { Text = "Here is some text!", Url = "http://www.google.com/#q=notifications" };
You could also use "dynamic" instead of "var", but that deprives you of compile-time checks, and it appears unnecessary in this case (because the type is fully defined at compile time, within the same method scope). A case where you would need to use "dynamic" is where you want to pass the anonymous-typed object as a parameter to another function, eg:
void Func1()
{
var userNotification = new { Text = "Here is some text!", Url = "http://www.google.com/#q=notifications" };
Func2(userNotification);
}
void Func2(dynamic userNotification)
{
string value = notification.Text;
}
Well you could declare the list as an list of dynimac objects:
List<dynamic> notificationList = new List<object>();
var userNotification = new { Text = "Here is some text!", Url = "http://www.google.com/#q=notifications" };
notificationList.Add(userNotification);
foreach(dynamic notification in notificationList)
{
string value = notification.Text;
}
or use var to let the compiler choose the type:
var notificationList = new []
{
new { Text = "Here is some text!", Url = "http://www.google.com/#q=notifications" }
}.ToList();
foreach(var notification in notificationList)
{
string value = notification.Text;
}

How to add multiple data types to list

I have my list as below,
var serie_line = new { name = series_name , data =new List<float?>() };
In the above code data in another list which contains float value, I want data to contains two different datatype value that is string and float value, when I am trying to add two different datatype values as follow,
var serie_line = new { name = series_name , data =new List<string, float?>() };
It gives me an error as
Using the generic type'System.Collections.Generic.List<T>' requires 1 argument.
I cannot try for data=new List<Tupple<string,float>>();..since I am using .NET 3.5...any idea..hw cn I deal with this problem..thank you,
----------Updated question---------
Output that I requires is as follows,
{
"legend":{"enabled":"true"},
"title":{"text":"Financial"},
"chart":{"type":"pie"},
"series":
[
{"name":"Actual-","data":[["Market Share",20.00],["Sales Growth",30.00],["Operating Profit",40.00],["Actual-Gross Margin %",10.00]]}
]
},
this data list should contains one string value and one float value...I want to draw pie chart in highcharts but output I am getting is as follows,
{
"legend":{"enabled":"true"},
"title":{"text":"Financial"},
"chart":{"type":"column"},
"series":[{"name":"Actual","data":[{"Str":"Market Share","Flo":20.00}]},
{"name":"Actual","data":[{"Str":"Sales Growth","Flo":30.00}]},
{"name":"Actual","data":[{"Str":"Operating Profit","Flo":40.00}]},
{"name":"Actual","data":[{"Str":"Gross Margin %","Flo":10.00}]}
]
}
Any Idea...???
----------Use of Dictionary----------
var data = new Dictionary<string, float?>();
var serie_line = new { name = series_name, data };
serie_line.data.Add(child_object_name, period_final_value);
but this doesnot give required output...
it only gives values inside data as for eg,
"data":["market share":20.00].. since I am serializing serie_line into JSON...but I don't want this way..what I want is "data":["market share",20.00]
I hope u get this...
just use
new Dictionary<string, float?>() //if your string value cannot be duplicated
//or
new List<KeyValuePair<string,float?> >
create a type to be use with your list:
public class MyDataType
{
public string Str {get; set;}
public float? Flo {get;set;}
}
you use it like this:
var serie_line = new { name = series_name , data =new List<MyDataType>() };
serie_line.data.Add(new MyDataType{Flo = 45.4});
or like:
var serie_line = new { name = series_name , data =new List<MyDataType>() };
serie_line.data.Add(new MyDataType{Flo = 45.4, Str = "my string"});
If you are trying to add items to a list so that both are available you need to use List<object>(), as its the only shared type between both. That or use ArrayList.
As you pull the objects out you will need to test if they are objects of type string or float? in order to cast them back. You may be able to wrap them.
Use ArrayList, the non-generic version of List.
How about something more structured:
public struct MyData
{
public float? FloatData;
public string StringData;
}
var serie_line = new
{
name = series_name,
data = new MyData()
{
FloatData = theFloatData,
StringData = theStringData,
}
};

Categories