I am getting a List of below class.
public class SmsResponse
{
public string AliasName { get; set; }
public string CellPhoneNumber { get; set; }
public int Response { get; set; }
}
I am passing this list to a function to check if the response field has response other than 0 , if it have than it is a error for which i have to prepare a status string by this method PrepareStatusString();.
bool isSuccess = EvaluateSmsResponse(responseList); //list of smsresponse class
private bool EvaluateSmsResponse(List<SmsResponse> smsResponseList)
{
bool isSent = smsResponseList.Exists(response => response.Response != 0);
if (!isSent)
PrepareStatusString(smsResponseList);
return isSent;
}
private void PrepareStatusString(List<SmsResponse> responseList)
{
bool isfirst = true;
foreach (var item in responseList)
{
if (item.Response != 0)
{
if(isfirst)
StatusDescription += item.AliasName + "|" + item.CellPhoneNumber + "|" + item.Response.ToString();
else
StatusDescription += "," + item.AliasName + "|" + item.CellPhoneNumber + "|" + item.Response.ToString();
isfirst = false;
}
}
}
The code is working as desired, but can it be optimized/improved in any way. I am feeling there is a scope improvement but not able to figure out ??
If you're using .NET 4 or newer, you can override SmsResponse.ToString() and then use String.Join<T>(String, IEnumerable<T>) to concatenate the responses.
So your SmsResponse class may look something like this:
public class SmsResponse
{
public string AliasName { get; set; }
public string CellPhoneNumber { get; set; }
public int Response { get; set; }
public override string ToString()
{
return AliasName + "|" + CellPhoneNumber + "|" +
Response.ToString();
}
}
And PrepareStatusString would be:
private void PrepareStatusString(List<SmsResponse> responseList)
{
StatusDescription = string.Join(",", responseList.Where(i => i.Response != 0));
}
StringBuilder will be more efficient at appending strings within the foreach loop (depending on num of iterations)
private void PrepareStatusString(List<SmsResponse> responseList)
{
bool isfirst = true;
StringBulder sb = new StringBuilder();
foreach (var item in responseList)
{
if (item.Response != 0)
{
if(isfirst)
sb.AppendFormat("{0}|{1}|{2}", item.AliasName, item.CellPhoneNumber,item.Response.ToString());
else
sb.AppendFormat(",{0}|{1}|{2}", item.AliasName, item.CellPhoneNumber, item.Response.ToString());
isfirst = false;
}
}
StatusDescription = sb.ToString();
}
I don't know about optimization, but it could be rewritten more expressively as follows:
private void PrepareStatusString(List<SmsResponse> responseList)
{
StatusDescription = responseList
.Where(x => x.Response != 0)
.Select(x => x.AliasName
+ "|" + x.CellPhoneNumber
+ "|" + x.Response.ToString())
.Aggregate((x, y) => x + "," + y);
}
Note that StringBuilder will only offer a noticeable performance benefit if you expect more than a couple hundred objects there.
Use string.Join like so
List<string> elements = new List<string>();
foreach (var item in responseList)
{
if (item.Response != 0)
{
elements.add(item.AliasName + "|" + item.CellPhoneNumber + "|" + item.Response.ToString());
}
}
string result = string.Join(",", elements.ToArray());
Related
OrderID=1211, OrderName=’Alice’, OrderDate= ‘15-10-2019’ //- row1
OrderID=1211, ItemID=1, ItemName=’Laptop’, ItemCompany=’Dell’, ItemPrice=’40000’ //row2
OrderID=1211, ItemID=2, ItemName=’Mouse’, ItemCompany=’Logitech’, ItemPrice=’5000’ //3
OrderID=4322, OrderName=’Ben’, OrderDate= ‘1-10-2019’//4
OrderID=4322, ItemID=1, ItemName=’Laptop’, ItemCompany=’Microsoft’, ItemPrice=’40000’//5
OrderID=4322, ItemID=2, ItemName= ‘Keyboard’, ItemCompany=’Microsoft’, ItemPrice=’12000’ //6
static void Main(string[] args)
{
Dictionary<dynamic, dynamic> yourDic = new Dictionary<dynamic, dynamic>();
StreamReader sr = new StreamReader(#"c:Probb.txt");
bool first = true;
while (sr.Peek() >= 0)
{
string line = sr.ReadLine();
string[] data = line.Split(',');
if (first == false)
{
if (!yourDic.ContainsKey(line.Split(',')[0]))
{
yourDic.Add(line.Split(',')[0], line.Split(',')[1] + "," + line.Split(',')[2]);
}
else if (!yourDic.ContainsKey(line.Split(',')[1]))
{
yourDic.Add(line.Split(',')[1], line.Split(',')[2] + "," + line.Split(',')[3] + "," + line.Split(',')[4]);
}
else
{
yourDic.Add(line.Skip(1), line.Split(',')[2] + "," + line.Split(',')[3] + "," + line.Split(',')[4]);
}
Console.WriteLine(line);
}
first = false;
}
foreach (KeyValuePair<dynamic, dynamic> kvp in yourDic)
{
Console.WriteLine(" {0},\n {1}", kvp.Key, kvp.Value);
}
}
}
}
Thanks for trying. I am new to C# and don't know how to access the specific data. output: OrderId:1211 Order Name=Alice, Total Id=2, Total Price=45000
Because the Dictionary must have a unique key, you need to save all order items in the same key. If I got you question correctly you want to get sum of item price for each OrderId.
By this way I think this should work:
public class Order
{
public string OrderName { get; set; }
public string OrderDate { get; set; }
public List<OrderItem> OrderItems { get; set; }
}
public class OrderItem
{
public int ItemId { get; set; }
public int ItemPrice { get; set; }
}
var dictItems = new Dictionary<string, Order>();
var allLines = File.ReadAllLines("test.txt").ToList();
foreach (var line in allLines)
{
var splitLine = line.Split(',');
if (dictItems.ContainsKey(splitLine[0]))
dictItems[splitLine[0]].OrderItems.Add(new OrderItem()
{
ItemId = int.Parse(splitLine[1].Split('=')[1]),
ItemPrice = int.Parse(splitLine[4].Split('=')[1].Replace("’", ""))
});
else
dictItems.Add(splitLine[0],
new()
{
OrderName = splitLine[1].Split('=')[1].Replace("’", ""),
OrderDate = splitLine[2].Split('=')[1].Replace("’", ""),
OrderItems = new List<OrderItem>()
});
}
foreach (var dictItem in dictItems)
{
Console.WriteLine(" {0},\n OrderName: {1} \n Total: {2} \n TotalPrice: {3}", dictItem.Key, dictItem.Value.OrderName, dictItem.Value.OrderItems.Count, dictItem.Value.OrderItems.Sum(x => x.ItemPrice));
}
Of course, you need to check the real data for preventing exception in convert string to int.
I have seen examples (and official ones) for IEnumerator on lists and arrays or dicts, but I have a different problem. I have classes with properties, how may I implement the IEnumerable and IEnumerator in that case?
My properties classes are:
public class standardMessage
{
public messageProperties message { get; set; }
public messageFlag flag { get; set; }
}
public class messageProperties
{
public string messageSubject { get; set; }
public string messageBody { get; set; }
}
public class messageFlag
{
public Boolean flagImportant { get; set; }
public Boolean flagPersonal { get; set; }
}
And this is the Program:
public class Program
{
static void Main(string[] args)
{
standardMessage myMessage = new standardMessage();
myMessage.message = new messageProperties
{
messageSubject = "Greetings",
messageBody = "Happy Weekend"
};
myMessage.flag = new messageFlag
{
flagImportant = false,
flagPersonal = true
};
//how do I iterate through all properties, without knowing how many are there, instead of writing this worm line of code?
Console.WriteLine(myMessage.message.messageSubject.ToString() + "\r\n" + myMessage.message.messageBody.ToString() + "\r\n" + myMessage.flag.flagImportant.ToString() + "\r\n" + myMessage.flag.flagPersonal.ToString());
Console.ReadLine();
}
}
If you want a production-grade way of printing your objects as a formatted string, you need to go and override ToString in all your classes to return whatever format you want.
However, if you just want to print the things on screen for debugging or logging purposes, why not JSON?
public static string ToJson(object #object) =>
System.Text.Json.JsonSerializer.Serialize(#object, new JsonSerializerOptions{WriteIndented = true});
Console.WriteLine(ToJson(myMessage));
Prints
{
"message": {
"messageSubject": "Greetings",
"messageBody": "Happy Weekend"
},
"flag": {
"flagImportant": false,
"flagPersonal": true
}
}
Quick and dirty, but quick and working.
I made a very primitive object to json converter. I wouldn't use this in production and it's about 30% slower than Newtonsoft but it get's the job done.
private static string PrintObject(object obj, int depth = 1)
{
var type = obj.GetType();
if (type.IsPrimitive || type == typeof(Decimal) || type == typeof(String))
return "\"" + obj.ToString() + "\"";
var props = type.GetProperties();
string ret = "";
for (var i = 0; i < props.Length; i++)
{
var val = props[i].GetValue(obj);
ret += new string('\t', depth) + "\"" + props[i].Name + "\":" + PrintObject(val, depth + 1);
if (i != props.Length - 1)
ret += "," + Environment.NewLine;
}
return ("{" + Environment.NewLine + ret + Environment.NewLine + new string('\t', depth - 1) + "}").Replace("\t", " ");
}
Gives the result
{
"message":{
"messageSubject":"Greetings",
"messageBody":"Happy Weekend"
},
"flag":{
"flagImportant":"False",
"flagPersonal":"True"
}
}
I have a SQlite based Xamarin Forms application on my Android Phone and Wear device. Syncing between my Phone and my Wear watch is performed according to my answer to another Question.
My database has the folowing tables Match and MatchStat:
public class Match
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public DateTime MatchDate { get; set; }
public TimeSpan MatchTime { get; set; }
public string Home { get; set; }
public string Guest { get; set; }
public int HomeScore { get; set; }
public int GuestScore { get; set; }
public bool Active { get; set; }
public bool Done { get; set; }
public string HomeColor { get; set; }
public string GuestColor { get; set; }
public Match()
{ }
}
public class MatchStat
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public int MatchId { get; set; }
public int ActionMin { get; set; }
public int HomeScore { get; set; }
public int GuestScore { get; set; }
public string ActionItem { get; set; }
public string PlayerName { get; set; }
public MatchStat()
{ }
}
If I want to sync my Match and all the MatchStat data from one device to the other I am doing it by mapping the data as strings in my MainActivity:
public async static void SendNewMatch(Match match, string path)
{
if (!client.IsConnected)
client.Connect();
await Task.Delay(200);
try
{
var request = PutDataMapRequest.Create(path);
var map = request.DataMap;
if (match != null)
{
map.PutString("Device", device);
map.PutString("Item", "AddMatch");
map.PutString("Home", match.Home);
map.PutString("Guest", match.Guest);
map.PutString("Active", match.Active.ToString());
map.PutString("Done", match.Done.ToString());
map.PutString("GuestScore", match.GuestScore.ToString());
map.PutString("HomeScore", match.HomeScore.ToString());
map.PutString("Date", match.MatchDate.Date.ToString());
map.PutString("Time", match.MatchTime.ToString());
map.PutLong("UpdatedAt", DateTime.UtcNow.Ticks);
await WearableClass.DataApi.PutDataItem(client, request.AsPutDataRequest());
}
request.UnregisterFromRuntime();
}
catch
{ }
finally
{
client.Disconnect();
}
}
public async static void SendMatchStat(MatchStat matchstat, Match match, int matchstatsize, string path)
{
if (!client.IsConnected)
client.Connect();
await Task.Delay(200);
try
{
var request = PutDataMapRequest.Create(path);
var map = request.DataMap;
MatchHelper mh = new MatchHelper();
if (matchstat != null)
{
map.PutString("Device", device);
map.PutString("Item", "MatchStat");
map.PutString("Home", match.Home);
map.PutString("Date", match.MatchDate.Date.ToString());
map.PutString("Time", match.MatchTime.ToString());
map.PutString("ActionItem", matchstat.ActionItem);
map.PutString("ActionMin", matchstat.ActionMin.ToString());
map.PutString("GuestScore", matchstat.GuestScore.ToString());
map.PutString("HomeScore", matchstat.HomeScore.ToString());
map.PutString("MatchStatSize", matchstatsize.ToString());
//map.PutString("PlayerName", matchstat.PlayerName.ToString());
map.PutLong("UpdatedAt", DateTime.UtcNow.Ticks);
await WearableClass.DataApi.PutDataItem(client, request.AsPutDataRequest());
}
request.UnregisterFromRuntime();
}
catch
{ }
finally
{
client.Disconnect();
}
}
public void ProcessMessage(Intent intent)
{
if (intent.GetStringExtra("Device") != device)
{
switch (intent.GetStringExtra("Item"))
{
case "AddMatch":
{
AddMatch(intent);
break;
}
case "MatchStat":
{
InsertMatchStat(intent);
break;
}
}
}
}
private void AddMatch(Intent intent)
{
MatchHelper mh = new MatchHelper();
if (bool.Parse(intent.GetStringExtra("Active")))
{
ObservableCollection<Match> activeMatches = mh.GetActiveMatches();
foreach (Match activeMatch in activeMatches)
{
mh.InactivateMatch(activeMatch);
}
}
Match newmatch = new Match();
newmatch.Home = intent.GetStringExtra("Home");
newmatch.Guest = intent.GetStringExtra("Guest");
newmatch.HomeColor = intent.GetStringExtra("HomeColor");
newmatch.GuestColor = intent.GetStringExtra("GuestColor");
newmatch.Active = bool.Parse(intent.GetStringExtra("Active"));
newmatch.Done = bool.Parse(intent.GetStringExtra("Done"));
newmatch.HomeScore = int.Parse(intent.GetStringExtra("HomeScore"));
newmatch.GuestScore = int.Parse(intent.GetStringExtra("GuestScore"));
newmatch.Active = bool.Parse(intent.GetStringExtra("Active"));
newmatch.Done = bool.Parse(intent.GetStringExtra("Done"));
newmatch.MatchDate = DateTime.Parse(intent.GetStringExtra("Date"));
newmatch.MatchTime = TimeSpan.Parse(intent.GetStringExtra("Time"));
mh.InsertMatch(newmatch);
}
private void InsertMatchStat(Intent intent)
{
MatchHelper mh = new MatchHelper();
Match match = mh.GetSpecificMatch(intent.GetStringExtra("Home"), DateTime.Parse(intent.GetStringExtra("Date")), TimeSpan.Parse(intent.GetStringExtra("Time")));
if (match != null)
{
MatchStat machstat = new MatchStat();
machstat.MatchId = match.Id;
machstat.ActionItem = intent.GetStringExtra("ActionItem");
machstat.ActionMin = int.Parse(intent.GetStringExtra("ActionMin"));
machstat.GuestScore = int.Parse(intent.GetStringExtra("GuestScore"));
machstat.HomeScore = int.Parse(intent.GetStringExtra("HomeScore"));
machstat.PlayerName = intent.GetStringExtra("PlayerName");
mh.InsertMatchStat(machstat);
}
}
In my WearService I have my OnDataChanged:
public override void OnDataChanged(DataEventBuffer dataEvents)
{
var dataEvent = Enumerable.Range(0, dataEvents.Count)
.Select(i => dataEvents.Get(i).JavaCast<IDataEvent>())
.FirstOrDefault(x => x.Type == DataEvent.TypeChanged && x.DataItem.Uri.Path.Equals(_syncPath));
if (dataEvent == null)
return;
//get data from wearable
var dataMapItem = DataMapItem.FromDataItem(dataEvent.DataItem);
var map = dataMapItem.DataMap;
Intent intent = new Intent();
intent.SetAction(Intent.ActionSend);
intent.PutExtra("Device", map.GetString("Device"));
intent.PutExtra("Item", map.GetString("Item"));
switch (map.GetString("Item"))
{
case "AddMatch":
{
intent.PutExtra("Home", map.GetString("Home"));
intent.PutExtra("Guest", map.GetString("Guest"));
intent.PutExtra("HomeColor", map.GetString("HomeColor"));
intent.PutExtra("GuestColor", map.GetString("GuestColor"));
intent.PutExtra("Active", map.GetString("Active"));
intent.PutExtra("Done", map.GetString("Done"));
intent.PutExtra("HomeScore", map.GetString("HomeScore"));
intent.PutExtra("GuestScore", map.GetString("GuestScore"));
intent.PutExtra("Date", map.GetString("Date"));
intent.PutExtra("Time", map.GetString("Time"));
LocalBroadcastManager.GetInstance(this).SendBroadcast(intent);
break;
}
case "MatchStat":
{
intent.PutExtra("Home", map.GetString("Home"));
intent.PutExtra("Date", map.GetString("Date"));
intent.PutExtra("Time", map.GetString("Time"));
intent.PutExtra("ActionItem", map.GetString("ActionItem"));
intent.PutExtra("ActionMin", map.GetString("ActionMin"));
intent.PutExtra("GuestScore", map.GetString("GuestScore"));
intent.PutExtra("HomeScore", map.GetString("HomeScore"));
intent.PutExtra("PlayerName", map.GetString("PlayerName"));
LocalBroadcastManager.GetInstance(this).SendBroadcast(intent);
break;
}
}
}
Instead of sending the data via separate strings I want to send my Match data as database file (if necessary as .ToString). Is it possible to achieve this and how can I thereafter retrieve the data.
Second of all I have my MatchStats as a list (IEnumerable or ObservableCollection). Is it possible to send this as a list or do I have to send each MatchStat seperately. By sending the Matchstats seperately my other device will not receive them in the desired order and not all MatchStats are received.
Instead of sending database data as database file I now solved this by sending the Matchstats in one file instead of sending all seperate data.
public async static void SendMatchStats(ObservableCollection<MatchStat> matchstats, Match match, int matchstatsize, string path)
{
if (!client.IsConnected)
client.Connect();
await Task.Delay(80);
try
{
var request = PutDataMapRequest.Create(path);
var map = request.DataMap;
MatchHelper mh = new MatchHelper();
int cnt = 1;
if (matchstatsize != 0)
{
map.PutString("Device", device);
map.PutString("Item", "MatchStats");
map.PutString("Home", match.Home);
map.PutString("Date", match.MatchDate.Date.ToString());
map.PutString("Time", match.MatchTime.ToString());
map.PutString("MatchStatSize", matchstatsize.ToString());
map.PutString("Path", path);
foreach (MatchStat matchstat in matchstats)
{
map.PutString("ActionItem" + cnt.ToString(), matchstat.ActionItem);
map.PutString("ActionMin" + cnt.ToString(), matchstat.ActionMin.ToString());
map.PutString("Color" + cnt.ToString(), matchstat.Color);
//map.PutString("ColorSchemeId", matchstat.ColorSchemeId.ToString());
map.PutString("GuestScore" + cnt.ToString(), matchstat.GuestScore.ToString());
map.PutString("HomeScore" + cnt.ToString(), matchstat.HomeScore.ToString());
if (matchstat.PlayerName == null)
map.PutString("PlayerName" + cnt.ToString(), "");
else
map.PutString("PlayerName" + cnt.ToString(), matchstat.PlayerName.ToString());
cnt++;
}
map.PutLong("UpdatedAt", DateTime.UtcNow.Ticks);
await WearableClass.DataApi.PutDataItem(client, request.AsPutDataRequest());
}
request.SetUrgent();
request.UnregisterFromRuntime();
}
catch
{ }
finally
{
client.Disconnect();
}
}
In my WearService I have my OnDataChanged:
case "MatchStats":
{
int size = int.Parse(map.GetString("MatchStatSize"));
intent.PutExtra("Home", map.GetString("Home"));
intent.PutExtra("Date", map.GetString("Date"));
intent.PutExtra("Time", map.GetString("Time"));
intent.PutExtra("MatchStatSize", map.GetString("MatchStatSize"));
intent.PutExtra("Path", map.GetString("Path"));
for (int cnt = 1; cnt <= size; cnt++)
{
intent.PutExtra("ActionItem" + cnt.ToString(), map.GetString("ActionItem" + cnt.ToString()));
intent.PutExtra("ActionMin" + cnt.ToString(), map.GetString("ActionMin" + cnt.ToString()));
intent.PutExtra("Color" + cnt.ToString(), map.GetString("Color" + cnt.ToString()));
intent.PutExtra("GuestScore" + cnt.ToString(), map.GetString("GuestScore" + cnt.ToString()));
intent.PutExtra("HomeScore" + cnt.ToString(), map.GetString("HomeScore" + cnt.ToString()));
intent.PutExtra("PlayerName" + cnt.ToString(), map.GetString("PlayerName" + cnt.ToString()));
Console.WriteLine("PutExtra " + map.GetString("ActionMin" + cnt.ToString()) + " min " + map.GetString("HomeScore" + cnt.ToString()) + "-" + map.GetString("GuestScore" + cnt.ToString()));
Console.WriteLine("GetStringExtra " + intent.GetStringExtra("ActionMin" + cnt.ToString()) + " min " + intent.GetStringExtra("HomeScore" + cnt.ToString()) + "-" + intent.GetStringExtra("GuestScore" + cnt.ToString()));
}
LocalBroadcastManager.GetInstance(this).SendBroadcast(intent);
break;
}
And in MainActivity I am processing the data in a seperate void InsertMatchstats:
private void InsertMatchStats(Intent intent)
{
MatchHelper mh = new MatchHelper();
Match match = mh.GetSpecificMatch(intent.GetStringExtra("Home"), DateTime.Parse(intent.GetStringExtra("Date")), TimeSpan.Parse(intent.GetStringExtra("Time")));
int size = int.Parse(intent.GetStringExtra("MatchStatSize"));
if (match != null)
{
for (int cnt = 1; cnt <= size; cnt++)
{
MatchStat matchstat = new MatchStat
{
MatchId = match.Id,
ActionItem = intent.GetStringExtra("ActionItem" + cnt.ToString()),
ActionMin = int.Parse(intent.GetStringExtra("ActionMin" + cnt.ToString())),
Color = intent.GetStringExtra("Color" + cnt.ToString()),
//ColorSchemeId = int.Parse(intent.GetStringExtra("ColorSchemeId"));
GuestScore = int.Parse(intent.GetStringExtra("GuestScore" + cnt.ToString())),
HomeScore = int.Parse(intent.GetStringExtra("HomeScore" + cnt.ToString())),
PlayerName = intent.GetStringExtra("PlayerName" + cnt.ToString()),
Sync = true
};
if (matchstat.Color == null)
matchstat.Color = "#FFFFFF";
MatchStat checkMatchStat = mh.CheckMatchStat(matchstat.HomeScore, matchstat.GuestScore, matchstat.ActionItem, matchstat.MatchId);
if (checkMatchStat == null)
mh.InsertMatchStat(matchstat);
else
{
checkMatchStat.ActionMin = matchstat.ActionMin;
checkMatchStat.Color = matchstat.Color;
//checkMatchStat.ColorSchemeId = matchstat.ColorSchemeId;
checkMatchStat.PlayerName = matchstat.PlayerName;
mh.UpdateMatchStat(checkMatchStat);
}
Console.WriteLine("PutExtra " + intent.GetStringExtra("ActionMin" + cnt.ToString()) + " min " + intent.GetStringExtra("HomeScore" + cnt.ToString()) + "-" + intent.GetStringExtra("GuestScore" + cnt.ToString()));
}
SendBack(intent.GetStringExtra("Path"));
}
}
Using this method the syncing is much faster and more precise. No data is lost and all data is received and processed in the right order.
I need help in appeding the string to path. The problem here is that the path that i have declare cannot be call, instead it just give normal string value. here is my code.
public static string inputhistory1 = System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) + "\\Log\\" + Process.GetCurrentProcess().ProcessName + DateTime.Now.ToString("yyyyMMdd")+".chf";
public static string inputhistory2 = System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) + "\\Log\\FileExtact" + DateTime.Now.AddMonths(-1).ToString("yyyyMM") + ".chf";
public static string inputhistory3 = System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) + "\\Log\\FileExtact" + DateTime.Now.AddMonths(-2).ToString("yyyyMM") + ".chf";
public static string inputhistory4 = System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) + "\\Log\\FileExtact" + DateTime.Now.AddMonths(-3).ToString("yyyyMM") + ".chf";
public static bool checkfile(string filename)
{
bool same = false;
for (i = 1; i <= 4; i++)
{
string filechf = "inputhistory" + i;
filechf = filechf;
try
{
foreach (string line in System.IO.File.ReadAllLines(filechf))
{
if (line.Contains(filename))
{
same = true;
break;
}
else
{
same = false;
}
}
}
catch (Exception)
{
// Ignore if file does not exist.
}
if (same == true)
{
break;
}
}
}
Just to show off the expressiveness of LINQ, and the power of leveraging the tools available:
List<string> inputHistories = new List<string>
{
inputhistory1, inputhistory2, inputhistory3, inputhistory4
};
public static bool checkfile(string filename)
{
return inputHistories.Any(filename =>
File.ReadLines(filename).Any(line => line.Contains(filename)));
}
That is because you assign variable filechf with string "inputhistory" + i.
Use an array or list to store input history value.
public static string inputhistory1 = System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) + "\\Log\\" + Process.GetCurrentProcess().ProcessName + DateTime.Now.ToString("yyyyMMdd")+".chf";
public static string inputhistory2 = System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) + "\\Log\\FileExtact" + DateTime.Now.AddMonths(-1).ToString("yyyyMM") + ".chf";
public static string inputhistory3 = System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) + "\\Log\\FileExtact" + DateTime.Now.AddMonths(-2).ToString("yyyyMM") + ".chf";
public static string inputhistory4 = System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) + "\\Log\\FileExtact" + DateTime.Now.AddMonths(-3).ToString("yyyyMM") + ".chf";
List<string> inputHistories = new List<string>();
inputHistories.Add(inputhistory1);
inputHistories.Add(inputhistory2);
inputHistories.Add(inputhistory3);
inputHistories.Add(inputhistory4);
Then you could access its value by index:
public static bool checkfile(string filename)
{
bool same = false;
//try
//{
for (i = 0; i < inputHistories.Count; i++)
{
string filechf = inputHistories[i];
try
{
foreach (string line in System.IO.File.ReadAllLines(filechf))
{
if (line.Contains(filename))
{
same = true;
break;
}
else
{
same = false;
}
}
}
catch (Exception)
{
//ignore if file does not exist
}
if (same == true)
{
break;
}
}
There are kinds of solutions may meet your requirements
you can store the variables in a dictionary:
var dictionary = new Dictionary<string,string>();
dictionary.Add("inputhistory1", inputhistory1);
dictionary.Add("inputhistory2", inputhistory2);
dictionary.Add("inputhistory3", inputhistory3);
dictionary.Add("inputhistory4", inputhistory4);
//use as below
Console.WriteLine(dictionary["inputhistory1"]);
or you can use reflection, for more information MSDN:
public class TestClass
{
public static string inputhistory1 = "value1";
public static string inputhistory2 = "value2";
public static string inputhistory3 = "value3";
public static string inputhistory4 = "value4";
}
var obj = new TestClass();
var field = typeof (TestClass).GetField("inputhistory1");
//use as below
Console.WriteLine(field.GetValue(obj));
even you can use switch/case to return your variable value
I have a list that I want to write to a CSV string.
The examples I have found all seem to be for single item lists, mine has multiple items.
The code I currently have is;
private static string CreateCSVTextFile<T>(List<T> data, string seperator = ",") where T : ExcelReport, new()
{
var objectType = typeof(T);
var properties = objectType.GetProperties();
var currentRow = 0;
var returnString = "";
foreach (var row in data)
{
var currentColumn = 0;
var lineString = "";
foreach (var info in properties)
{
lineString = lineString + info.GetValue(row, null) + seperator;
currentColumn++;
}
if (seperator != "")
{
lineString = lineString.Substring(0, lineString.Count() - 2);
}
returnString = returnString + Environment.NewLine + lineString;
currentRow++;
}
return returnString;
}
But when the list is large this method takes a very long time to run.
The class my list is based on looks like;
internal class ClientMasterFile
{
public String COL1{ get; set; }
public String COL2{ get; set; }
public String COL3{ get; set; }
public String COL4{ get; set; }
public String COL5{ get; set; }
public String COL6{ get; set; }
public String COL7{ get; set; }
public String COL8{ get; set; }
public String COL9{ get; set; }
public String COL10{ get; set; }
public String COL11{ get; set; }
public String COL12{ get; set; }
}
Is there a faster way to do this using an advanced version of String.Join?
Thanks
Your method can be simplified using StringBuilder and string.Join.
Concatenating strings directly is slow and uses a lot of memory which is fine for small operations.
See: Does StringBuilder use more memory than String concatenation?
private static string CreateCSVTextFile<T>(List<T> data, string seperator = ",")
{
var properties = typeof(T).GetProperties();
var result = new StringBuilder();
foreach (var row in data)
{
var values = properties.Select(p => p.GetValue(row, null));
var line = string.Join(seperator, values);
result.AppendLine(line);
}
return result.ToString();
}
A more complete implementation for CSVs:
private static string CreateCSVTextFile<T>(List<T> data)
{
var properties = typeof(T).GetProperties();
var result = new StringBuilder();
foreach (var row in data)
{
var values = properties.Select(p => p.GetValue(row, null))
.Select(v => StringToCSVCell(Convert.ToString(v)));
var line = string.Join(",", values);
result.AppendLine(line);
}
return result.ToString();
}
private static string StringToCSVCell(string str)
{
bool mustQuote = (str.Contains(",") || str.Contains("\"") || str.Contains("\r") || str.Contains("\n"));
if (mustQuote)
{
StringBuilder sb = new StringBuilder();
sb.Append("\"");
foreach (char nextChar in str)
{
sb.Append(nextChar);
if (nextChar == '"')
sb.Append("\"");
}
sb.Append("\"");
return sb.ToString();
}
return str;
}
Using: escaping tricky string to CSV format
we use linqtocsv with some success
https://linqtocsv.codeplex.com
and here is some explanation
http://www.codeproject.com/Articles/25133/LINQ-to-CSV-library