transforming to linq [closed] - c#

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Is it possible to transform following code to Linq that it will look like little bit more nicely
foreach (var entry in bottleneck.Item2)
{
if(entry.ChangeoverTime > 0)
{
avarangechangeOverTimes += entry.ChangeoverTime;
++counter;
}
if (entry.ChangeoverTime > maxchangeOverTimes)
{
maxchangeOverTimes = entry.ChangeoverTime;
}
changeovertime.ChangeoverTimes.Add
(
new ChangeOverDateValue
{
ChangeoverValue = entry.ChangeoverTime,
Color = ChangeOverTimeToColor(entry.ChangeoverTime),
StartTime = entry.StartTime
}
);
}

If the number of entries in bottleneck.Item2 isn't huge, you could achieve the same using these three statements:
var maxChangeOverTime = bottleneck.Item2.Max(x => x.ChangeoverTime);
var averageChangeOverTime = bottleneck.Item2.Average(x => x.ChangeoverTime);
var result
= bottleneck.Item2
.Select(x => new ChangeOverDateValue
{
ChangeoverValue = x.ChangeoverTime,
Color = ChangeOverTimeToColor(x.ChangeoverTime),
StartTime = x.StartTime
});
changeovertime.ChangeoverTimes.AddRange(result);
Please note that this will enumerate bottleneck.Item2 three times instead of one time with your current code.

I think that you can only change the external foreach:
bottleneck.Items2.ToList().Foreach(entry =>
{
// your code
});

bottleneck.Item2.where(entry => entry.ChangeoverTime).ToList().Foreach(entry => {
avarangechangeOverTimes += entry.ChangeoverTime;
++counter;
});
maxchangeOverTimes = bottleneck.Item2.max=(entry => entry.ChangeoverTime);
changeovertime.ChangeoverTimes.AddAll(bottleneck.Item2.select(entry => new new ChangeOverDateValue
{
ChangeoverValue = entry.ChangeoverTime,
Color = ChangeOverTimeToColor(entry.ChangeoverTime),
StartTime = entry.StartTime
}));
this is all i can come up with without having more info or my development envirment with me

Maybe...
var avarangechangeOverTimes = bottleneck.Item2
.Where(entry => entry.ChangeOverTime > 0)
.Sum(entry => entry.ChangeOverTime);
var maxchangeOverTimes = bottleneck.Item2
.Max(entry => entry.ChangeOverTime);
bottleneck.Item2.ToList()
.ForEach(entry => changeovertime.ChangeoverTimes.Add
(
new ChangeOverDateValue {
ChangeoverValue = entry.ChangeoverTime,
Color = ChangeOverTimeToColor(entry.ChangeoverTime),
StartTime = entry.StartTime
}
)
);

Try this:
var averagechangeOverTimes = bottleneck.Item2
.Where(entry => entry.ChangeoverTime > 0)
.Sum(entry => entry.ChangeoverTime);
counter = bottleneck.Item2.Count(entry => entry.ChangeoverTime > 0);
var maxchangeOverTimes = bottleneck.Item2.Max(entry => entry.ChangeoverTimes);
changeovertime.ChangeoverTime.Add(bottleneck.Item2
.Select(entry => new ChangeOverDateValue{
ChangeoverValue = entry.ChangeoverTime,
Color = ChangeOverTimeToColor(entry.ChangeoverTime),
StartTime = entry.StartTime
});

Related

remove loop in linq cause slow the performance [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
want to remove foreach loop and done with Linq....Please suggest
In ViewModal I have LeadStatus Name and in LeadModal i have Id of LeadStatus on basis of Id I have to fatch Name from LeadStatusTable and bind in ViewModal
Thanks
List<Entities.LeadViewModel> leadViewModels = new List<Entities.LeadViewModel>();
IEnumerable<Entities.Lead> leads = await _leadRepository.AllNonDeletedAndConvertedLeads();
foreach (var lead in leads)
{
Entities.ChetuUser chetuUser = await _chetuUserRepository.GetChetuUser(lead.OwnerId);
if (!string.IsNullOrEmpty(lead.Status))
{
LeadStatusMaster leadStatusMaster = await _masterTableRepository.LeadStatusMasterById(lead.Status);
if (chetuUser != null && leadStatusMaster != null)
{
leadViewModels.Add(new Entities.LeadViewModel
{
LeadProperty = lead,
LeadStatusName = leadStatusMaster.Name,
CreatedDate = lead.CreatedDate
});
}
else if (chetuUser != null && leadStatusMaster == null)
{
leadViewModels.Add(new Entities.LeadViewModel
{
LeadProperty = lead,
LeadStatusName = "",
CreatedDate = lead.CreatedDate
});
}
else
{
leadViewModels.Add(new Entities.LeadViewModel
{
LeadProperty = lead,
LeadStatusName = "",
CreatedDate = lead.CreatedDate,
OwnerName = ""
});
}
}
else
{
if (chetuUser != null)
{
leadViewModels.Add(new Entities.LeadViewModel
{
LeadProperty = lead,
LeadStatusName = "",
CreatedDate = lead.CreatedDate,
OwnerName = chetuUser.EmployeeName
});
}
}
}
return leadViewModels;
Your title is different by the asked question. Because you speak about the speed replaceing the foreach with linq will not speed up your loop. The problem is the awaits in it. Moreover the linq's foreach is a little tricky to work with await:
C# async await using LINQ ForEach()

Replacing loops with linq code [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
My current code is like this:
var results = new List<Results>();
var items = new List<string>
{
"B,0",
"A,1",
"B,2",
"A,3",
"A,4",
"B,5",
"A,6",
"A,7",
"B,8"
};
int size = 2;
int temp;
var tempResults = new List<int>();
var keys = items.Select(t => t.Split(',')[0]).Distinct().ToList();
//var values = items.Select(t => t.Split(',')[1]).ToList();
//var result = items.SelectMany(k => values, (k, v) => new {k, v});
foreach (var key in keys)
{
temp = 0;
tempResults = new List<int>();
foreach (var item in items)
{
if (item.Split(',')[0] == key)
{
tempResults.Add(Int32.Parse(item.Split(',')[1]));
temp++;
}
if (temp == size)
{
results.Add(new Results
{
Key = key,
Values = new List<int>(tempResults)
});
temp = 0;
tempResults.Clear();
}
}
}
foreach (Results r in results)
{
Console.WriteLine("Key: " + r.Key);
Console.WriteLine("Values: ");
foreach (int i in r.Values)
{
Console.WriteLine(i);
}
}
Everything works fine with it, but I am using two loops to get the results needed. I want to replace them with a LINQ expression and been trying, but can't seem to figure it out. Any help is appreciated.
You could use a combination of LINQ methods: .GroupBy, .Select, SelectMany and some data structures like Tuple<T1, T2>.
Provided that we have class:
class Results
{
public string Key { get; set; }
public List<int> Values { get; set; }
}
The solution could be:
int k = 0;
var result =
items.Select(x => // parse initial string
{
var strValue = x.Split(',');
return Tuple.Create(strValue[0], Convert.ToInt32(strValue[1]));
})
.GroupBy(x => x.Item1, y => y.Item2) // group by key
.Select(x => Tuple.Create(x.Key, x)) // flatten to IEnumerable
.SelectMany(x => // select fixed size data chunks
x.Item2.GroupBy(y => k++ / size, z => z)
.Select(z => Tuple.Create(x.Item1, z)))
.Select(x => // cast to resulting model type
new Results()
{
Key = x.Item1,
Values = x.Item2.ToList()
})
.ToList(); // Return enumeration as list
How about writing a couple extension methods?
const int partitionSize = 2;
var itemLookup = items.ToLookup(x => x.Split(',')[0], x => Int32.Parse(x.Split(',')[1]));
var partitionedItems = itemLookup.Partition(partitionSize);
foreach (var partition in partitionedItems)
foreach (var lookup in partition)
{
Console.WriteLine("Key: " + lookup.Key);
Console.WriteLine("Values: ");
foreach (var i in lookup.ToList())
{
Console.WriteLine(i);
}
}
public static class PartitionExtensions
{
public static IList<ILookup<K, V>> Partition<K, V>(this ILookup<K, V> lookup, int size)
{
return lookup.SelectMany(l => l.ToList().Partition(size).Select(p => p.ToLookup(x => l.Key, x => x))).ToList();
}
public static IList<IList<T>> Partition<T>(this IList<T> list, int size)
{
IList<IList<T>> results = new List<IList<T>>();
var itemCount = list.Count();
var partitionCount = itemCount / size;
//your paritioning method is truncating items that don't make up a full partition
//if you want the remaining items in a partial partition, use this code instead
//var partitionCount = ((itemCount % size == 0) ? itemCount : itemCount + size) / size;
for (var i = 0; i < partitionCount; i++)
{
results.Add(list.Skip(i * size).Take(size).ToList());
}
return results;
}
}
Not really a way to remove the inner loop, but you could shorten a bit your code with:
....
var keys = items.Select(t => t.Split(',')[0]).Distinct().ToList();
foreach (var key in keys)
{
var forKey = items.Where(x => x.Split(',')[0] == key)
.Select(k => int.Parse(k.Split(',')[1]));
for (int x = 0; x < forKey.Count(); x += size)
{
results.Add(new Results
{
Key = key,
Values = forKey.Skip(x).Take(size).ToList()
});
}
}
....
At least this approach will remove the need of the temporary variables and all the if checks inside the loop and will also include in your results the last value for the A key that has only one integer in its list.

get a total value from loop items [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Check the code bellow. I am looping to get all value of a returned XML response. But i want to get a total value of all nofwatch variable. How can i add them to get a total value? any idea?
foreach (var sri in searchResultItems)
{
// Get all xml elements
var childElements = sri.Elements();
var nofwatch = childElements.FirstOrDefault(x => x.Name.LocalName == "listingInfo")
.Elements().FirstOrDefault(x => x.Name.LocalName == "watchCount");
//add items from xml data to EbayDataViewModel object
items.Add(new EbayDataViewModel
{
TotalWatchers = nofwatch.Value //how can do + result of all nofwatch value?
});
ViewBag.TotalWatchers = TotalWatchers;
}
var totalValue = 0; //delcare the variable outside the foreach loop
foreach (var sri in searchResultItems)
{
// Get all xml elements
var childElements = sri.Elements();
var nofwatch = childElements.FirstOrDefault(x => x.Name.LocalName == "listingInfo")
.Elements().FirstOrDefault(x => x.Name.LocalName == "watchCount");
//now use += operator to add the result to the totalValue variable
//totalValue += nofwatch.Value;
//nofwatch.Value should be of type string and you would need to parse it as an integer first if that truely is the case
var intValue = 0;
if (int.TryParse(nofwatch.Value, out intValue) == false)
continue;
totalValue += intValue;
}
//outside of the foreach loop use totalValue to set the desired member
ViewBag.TotalWatchers = totalValue;

How to get the Split value from collection [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I have the following key value pair in an array, and am trying to extract and load them into a collection.
The below code is working but it can be optimized using linq:
string _data = "Website=url:www.site1.com,isdefault:true,url:www.site2.com,isdefault:true";
List<WebSiteAddress> _websiteList = new List<WebSiteAddress>() ;
WebSiteAddress _website = new WebSiteAddress();
string[] _websiteData = _divider[1].Split('=');
string[] _WebsiteKeyValuePair = _websiteData[1].Split(',');
for (int j = 0; j < _WebsiteKeyValuePair.Length; j++)
{
string key = _WebsiteKeyValuePair[j].Split(':')[0];
string value = _WebsiteKeyValuePair[j].Split(':')[1];
if (key.ToLower() == "url")
{
_initWebsite.Url = value;
}
else if (key.ToLower() == "isdefault")
{
_website.IsDefault = Convert.ToBoolean(value);
_websiteList.Add(_website);
}
}
You can do something like:
string _data = "Website=url:www.site1.com,isdefault:true,url:www.site2.com,isdefault:true";
List<WebSiteAddress> _websiteList = _data
.Split(new string[]{"url:"}, StringSplitOptions.RemoveEmptyEntries)
.Select(site => site.Split(new char[]{','}, StringSplitOptions.RemoveEmptyEntries))
.Where(site => site.Length > 1)
.Select(site => new WebSiteAddress { Url = site[0], IsDefault = site[1].ToLower().Replace("isdefault:", "") == "true"})
.ToList();

using HtmlAgilityPack [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have a problem HtmlAgilityPack, I would like the following image. but it does not coincide with the lines. What can I do?
HtmlWeb web = new HtmlWeb();
web.OverrideEncoding = Encoding.GetEncoding("windows-1254");
HtmlAgilityPack.HtmlDocument doc = web.Load("http://www.yerelnet.org.tr/belediyeler/belediye.php?belediyeid=129531");
var nufus = doc.DocumentNode.SelectNodes("/html/body/center/table/tr/td[2]/table/tr[2]/td[2]/table/tr[2]/td/table/tr/td/table[5]/tr/td[2]/table/tr/td[3]/table[2]");
string str = String.Empty;
string line = String.Empty;
if (nufus != null)
{
for (int i = 0; i < nufus.Count; i++)
{
str += nufus[i].InnerText.Replace(" ", "").Replace("\t", "").Replace("Nüfus Bilgileri", "");
string[] s = str.Split('\n');
for (int x = 10; x < s.Count(); x++)
{
if (s[x] != String.Empty && s[x] != " ")
{
lnufus.Add(s[x].ToString());
lnufus.Add(s[x].ToString());
lnufus.Add(s[x].ToString());
lnufus.Add(s[x].ToString());
}
}
}
}
dataGridView1.DataSource = lnufus.GroupBy(x => x).Select(g => new
{
Yıl = g.Key, Toplam = g.Key, Kadin = g.Key, Erkek = g.Key
}).ToList();
No need for that strange xpath query. This should work
var nufus = doc.DocumentNode.SelectNodes("//table[#class='belediyeler']/tr")
.Skip(1)
.Select(tr => tr.Elements("td").Select(td => td.InnerText).ToList())
.Select(td => new { Yil = td[0], Toplam = td[1], Kadin = td[2], Erkek = td[3] })
.ToList();
dataGridView1.DataSource = nufus;

Categories