I have a array (with type of Object) which I'm extracting from a System.Collections.ArrayList. And I'm now trying to cast this object to a int[] so i can use it to compare it with another int[].
Note: I'm currently using .Net Framework 7.0.0
var query = (from el in l
where el.ID_Seal_From != "" && el.ID_Seal_From != null
select new
{
conn = el.Conn_from,
seal = el.ID_Seal_From
}).ToList();
var query2 = (from el in l
where el.ID_Seal_To != "" && el.ID_Seal_To != null
select new
{
conn = el.Conn_to,
seal = el.ID_Seal_To
}).ToList();
var res = query.Concat(query2).ToList();
ArrayList arrLi = new();
List<int> indexOfEqualElements = new();
for (int i = 0; i < res.Count; i++)
{
for (int j = 0; j < res.Count; j++)
{
if (res[i].seal.CompareTo(res[j].seal) == 0)
{
indexOfEqualElements.Add(j);
}
}
if (Contains(arrLi, indexOfEqualElements.ToArray()) == -1) //to avoid multiple entries
{
arrLi.Add(indexOfEqualElements.ToArray());
}
indexOfEqualElements.Clear();
}
In the "contains" call I'm trying to compare the Elements. For this case i need to avoid, that two equal arrays get added to the list. Because afterwards i need this distinct dataset to continue
I'm sorry for not trying to understand all the code above, but you simply can cast all the values of an ArrayList to an IEnumerable like this:
var arrayList = new ArrayList(2)
{
1,
2
};
var integerEnumerable = arrayList
.Cast<int>();
Feel free to add an .ToArray(), if you like an int[] instead.
ArrayList is deprecated. If you wanted a list you should use List<int>. In this instance, it seems you actually need something like a HashSet<int>.
But to just get distinct elements you can simply use DistinctBy.
var query = (
from el in l
where el.ID_Seal_From != "" && el.ID_Seal_From != null
select new
{
conn = el.Conn_from,
seal = el.ID_Seal_From
});
var query2 = (
from el in l
where el.ID_Seal_To != "" && el.ID_Seal_To != null
select new
{
conn = el.Conn_to,
seal = el.ID_Seal_To
});
var res = query.Concat(query2).DistinctBy(el => el.seal);
Related
I have a linq which is inside a for loop,im adding the results to a list using addRange() but it will add whole thing in a single set,for example my first loop result has 16 items,the second has 10 items,...i want them to be added to list like this then i can see in list how many and which items has been added on each query
public List<statisticsDaily> dailyStat(List<string> id,string dtFrom,string dtTo)
{
List<StatisticsDaily> rsltofquery = new List<StatisticsDaily>();
for (int i = 0; i < id.Count; i++)
{
var rslt = (from d in db.statDaily
join s in db.masterData on d.m_turbine_id equals s.m_turbine_id
where d.m_turbine_id == IPAddress.Parse(id[i]) && d.m_date >= frm && d.m_date <= to
select new StatisticsDaily
{
m_wind_speed = d.m_wind_speed,
Date = d.m_date.ToString("yyyy-MM-dd"),
name = s.turbine_name,
Production = d.m_energy_prod,
Availability = d.m_corrected_av
}
).AsEnumerable().OrderBy(s => s.Date).ToList();
rsltofquery.AddRange(rslt);
}
You need to have collection of collections like List<List<StatisticsDaily>>.
So yours code will be:
public List<List<statisticsDaily>> dailyStat(List<string> id,string dtFrom,string dtTo)
{
List<List<StatisticsDaily>> rsltofquery = new List<List<StatisticsDaily>>();
for (int i = 0; i < id.Count; i++)
{
var rslt = (from d in db.statDaily
join s in db.masterData on d.m_turbine_id equals s.m_turbine_id
where d.m_turbine_id == IPAddress.Parse(id[i]) && d.m_date >= frm && d.m_date <= to
select new StatisticsDaily
{
m_wind_speed = d.m_wind_speed,
Date = d.m_date.ToString("yyyy-MM-dd"),
name = s.turbine_name,
Production = d.m_energy_prod,
Availability = d.m_corrected_av
}).AsEnumerable().OrderBy(s => s.Date).ToList();
rsltofquery.Add(rslt);
}
}
If you want to use all elements, not in parts, you can use SelectMany:
var x = dailyStat(id, dtFrom, dtTo);
foreach (var e in x.SelectMany(d => d)) ...
I'm having a problem with performance in my code.
The method below is used to create a comparative score of companies from the whole country based some rules:
public List<object> GetCNAEBRCycleChart(int VisitId)
{
List<object> result = new List<object>();
Visit visit = Context.Visit.Find(VisitId);
Company company = visit.Company;
var CNAE = company.MainEconomicCNAE.IdentifyCNAE;
string[] Themes = new string[5];
Themes[0] = "Finance";
Themes[1] = "Market";
Themes[2] = "Organization";
Themes[3] = "Planning";
Themes[4] = "People";
int count = 0;
List<Visit> listVisitCNAECountry = (from vis in Context.Visit
where vis.Company.MainEconomicCNAE.IdentifyCNAE.StartsWith(CNAE)
&& vis.Order == 1
select vis
).ToList();
double[] Values = new double[5];
Values[0] = 0;
Values[1] = 0;
Values[2] = 0;
Values[3] = 0;
Values[4] = 0;
foreach (var vis in listVisitCNAECountry)
{
count = 0;
var visitIdCompany = vis.Id;
var diagnostic = Context.Visit.Find(visitIdCompany).Diagnostic;
if (diagnostic != null)
{
foreach (var itemTheme in Themes)
{
var TemaAux = itemTema;
int QtQuestion = (from itemForm in Context.FormItem
join tipo in Context.FormItemType on itemForm.FormItemTypeId equals tipo.Id
join itemForm2 in Context.FormItem on itemForm.FormItemParentId equals itemForm2.Id
join itemForm3 in Context.FormItem on itemForm2.FormItemParentId equals itemForm3.Id
where itemForm3.Name == TemaAux && tipo.Name == "Pergunta"
select itemForm
).Count();
var sumAnswerCompany = (from alter in Context.Alternative
join itemForm in Context.FormItem on alter.FormItemId equals itemForm.Id
join itemForm2 in Context.FormItem on itemForm.FormItemParentId equals itemForm2.Id
join itemForm3 in Context.FormItem on itemForm2.FormItemParentId equals itemForm3.Id
join answer in Context.Answer on itemForm.Id equals answer.FormItemId
where answer.AlternativeId == alter.Id &&
answer.DiagnosticId == diagnostico.Id && itemForm3.Name == TemaAux
select alter.Value
).AsEnumerable().Sum();
double scoreCompany = //Some calculations
Values[count] += scoreCompany;
count++;
}
}
}
count = 0;
foreach (var val in Values)
{
Values[count] = //more calculations
count++;
}
var model = new { NameCategory = "CNAE in Country", Value1 = Values[0], Value2 = Values[1], Value3 = Values[2], Value4 = Values[3], Value5 = Values[4] };
result.Add(model);
return result;
}
The problem is that, with the actual CNAE, the list listVisitCNAECountry gets 16000+ elements, which make for terrible performance.
In my localhost environment it's taking 30min+ and I don't even know where to begin to actually improve the performance.
The biggest problem is that I really need all those iterations to make the calculations right.
If anyone has any ideas, please, help me.
The first thing to change is:
var sumAnswerCompany = ( /* complex query */
).AsEnumerable().Sum();
This is bad; instead of issuing select sum(...) as a database query, it instead will have to select the column(s) and return all the rows required, which may be a huge amount of bandwidth.
Instead, do the sum at the database and just bring back one number:
var sumAnswerCompany = ( /* complex query */
).Sum();
However, frankly I'd suggest writing the entire thing in raw SQL using joins and grouping from the original data. Sometimes LINQ isn't your best tool.
I have a query that I want to substitue the foreach with linq because the foreach is so slow
how can I write all this codein one query
this is my code:
ret = new List<ReportData>();
foreach (var item in Number)
{
string A = item.Substring(0, 11);
string B = item.Substring(14, 2);
string C = item.Substring(19, 11);
string D = item.Substring(33);
ret1 = (from a in Report
where a.A == A && a.B == B && a.C == C && a.D == D && Filter.Type.Contains(a.Y)
select new ReportData
{
X = a.X,
Y = a.Y,
});
if (ret1 != null && ret1.ToList().Count > 0)
{
ret.AddRange(ret1);
}
}
As already mentioned in the comments, LINQ will not make a foreach any faster; if you have to iterate the entire collection, then foreach will be faster than LINQ.
There is no need to check for null or if any results exists in the inner LINQ statement; just add the range since the LINQ query will return an Enumerable.Empty<ReportData> if nothing is returned from the query.
if (ret1 != null && ret1.ToList().Count > 0)
{
ret.AddRange(ret1);
}
// becomes
ret.AddRange(ret1);
Assumming Number is a collection of string, make sure there are no duplicates:
foreach (string item in Number.Distinct())
If Number is a large list, thousands of items or more, then consider using a Parallel.ForEach.
Linq will just enumerate the collection just like a foreach would, but you might see some benefit from a join:
var items = Number.Select( item => new {
A = item.Substring(0, 11),
B = item.Substring(14, 2),
C = item.Substring(19, 11),
D = item.Substring(33),
});
var ret = (from a in Report
join i in items
on new {a.A, a.B, a.C, a.D} equals new {i.A, i.B, i.C, i.D}
where Filter.Type.Contains(a.Y)
select new ReportData
{
X = a.X,
Y = a.Y,
});
All I want to do is declare var place correctly so it is still in scope once I get to the foreach loop. I'm assuming I need to declare it before the if statement for connections. Is this a correct assumption and if so how do I declare it? Thanks!
using (var db = new DataClasses1DataContext())
{
if (connections == "Connections")
{
var place = (from v in db.pdx_aparts
where v.Latitude != null && v.Region == region && v.WD_Connect >= 1
select new
{
locName = v.Apartment_complex.Trim().Replace(#"""", ""),
latitude = v.Latitude,
longitude = v.Longitude
}).Distinct().ToArray();
}
else
{
var place = (from v in db.pdx_aparts
where v.Latitude != null && v.Region == region && ((v.WD_Connect == null) || (v.WD_Connect == 0))
select new
{
locName = v.Apartment_complex.Trim().Replace(#"""", ""),
latitude = v.Latitude,
longitude = v.Longitude
}).Distinct().ToArray();
}
foreach (var result in place)
....
You can create an array with a single entry whose value you ignore later:
// Note: names *and types* must match the ones you use later on.
var place = new[] { new { locName = "", latitude = 0.0, longitude = 0.0 } };
if (connections = "Connections")
{
// Note: not a variable declaration
place = ...;
}
else
{
place = ...;
}
This works because every use of anonymous types using properties with the same names and types, in the same order, will use the same concrete type.
I think it would be better to make the code only differ in the parts that it needs to though:
var query = v.db.pdx_aparts.Where(v => v.Latitude != null && v.Region == region);
query = connections == "Connections"
? query.Where(v => v.WD_Connect >= 1)
: query.Where(v => v.WD_Connect == null || v.WD_Connect == 0);
var places = query.Select(v => new
{
locName = v.Apartment_complex
.Trim()
.Replace("\"", ""),
latitude = v.Latitude,
longitude = v.Longitude
})
.Distinct()
.ToArray();
Here it's much easier to tell that the only part which depends on the connections value is the section of the query which deals with WD_Connect.
You could convert the if to a ?:.
var place = connections == "Connections" ? monsterQuery1 : monsterQuery2;
I do not think this is a good solution because your queries are too big (unreadable).
It would be much better if you introduced a named class that you use instead of the anonymous type. R# does that for you in a "light bulb menu" refactoring.
you could just use the 1 query since they are pretty much the same, and just add the extra condition in the where clause
var place = (from v in db.pdx_aparts
where v.Latitude != null && v.Region == region
&& connections == "Connections"
? v.WD_Connect >= 1
: ((v.WD_Connect == null) || (v.WD_Connect == 0))
select new
{
locName = v.Apartment_complex.Trim().Replace(#"""", ""),
latitude = v.Latitude,
longitude = v.Longitude
}).Distinct().ToArray();
foreach (var result in place)
....
I have class like:
class SortNode
{
public Int32 m_valRating = 0;
public SortNode(Int32 valRating)
{
this.m_valRating = valRating;
}
}
and some list refSortNodeList:
List<SortNode> refSortNodeList = new List<SortNode>();
Random refRandom = new Random();
for (int i = 0; i < 100; ++i)
{
refSortNodeList.Add(new SortNode(refRandom.Next(-10, 30)));
}
foreach (var varSortNode in refSortNodeList)
{
Console.WriteLine("SortNode rating is {0}", varSortNode.m_valRating);
}
How to sort easily my refSortNodeList by m_valRating field? Or maybe I need to use some another List class?
list.Sort((x,y) =>
x.m_valRating.CompareTo(y.m_valRating));
In-place:
refSortNodeList.Sort(
(x, y) =>
x == null ? (y == null ? 0 : -1)
: (y == null ? 1 : x.m_valRating.CompareTo(y.m_valRating))
);
Creating a new enumeration:
var newEnum = refSortNodeList.OrderBy(x => x.m_valRating);
Creating a new list:
var newList = refSortNodeList.OrderBy(x => x.m_valRating).ToList();
In-place is fastest and most memory efficient, but no good if you want to also retain the old list.
The next is faster than the last and gives results as they go, but you have to re-do the sort to use it again, in which case the third is the one to go for.
Use Linq order by.
var mySortedList = refSortNodeList.OrderBy(x => x.m_valRating);
Here is a real live example where I am pulling a list from a database but it is exactly the same concept.
vendorProducts = (from vp in db.COMPANIES_VND_PRODUCTS
join p in db.CT_CT_INV_CLASSES on vp.CLASS_ID equals p.CLASS_ID
join m in db.CT_CT_MODALITY_CODES on vp.MODALITY_ID equals m.MODALITY_ID
where vp.COMPANY_ID == companyId
select new ProductTypeModality
{
Active = p.ACTIVE.Equals("Y") ? true : false,
BioMedImaging = p.BIOMED_IMAGING,
Code = p.CLASS_CODE,
Description = p.DESCRIPTION,
Id = p.CLASS_ID,
PricingMargin = p.PRICING_MARGIN,
ModalityCode = m.MODALITY_CODE,
ModalityId = m.MODALITY_ID,
VendorId = companyId
}).OrderBy(x => x.Code).ToList<ProductTypeModality>();
Implement IComparable<T>
You can use Linq for basic sorts:
refSortNodeList.OrderBy(n => n.m_valRating);
If you need more complex sorting your will need to implement IComparable to use the built in sorting.
Try this:
refSortNodeList.Sort(new delgate(SortNode x, SortNode y)
{
return x.CompareTo(y);
}
);
It's easy using linq:
var newlist = refSortNodeList.sort( n => n.m_valRating );
List<SortNode> refSortNodeList = new List<SortNode> ();
Random refRandom = new Random ();
for (int i = 0; i < 100; ++i) {
refSortNodeList.Add (new SortNode (refRandom.Next (-10, 30)));
}
// Use this (Linq) if you're using .NET 3.5 or above.
var sortedList = refSortNodeList.OrderBy (node => node.m_valRating);
foreach (var varSortNode in sortedList) {
Console.WriteLine ("SortNode rating is {0}", varSortNode.m_valRating);
}
// Use this otherwise (e.g. .NET 2.0)
refSortNodeList.Sort (
delegate (SortNode n1, SortNode n2) {
return n1.m_valRating.CompareTo (n2.m_valRating);
}
);
foreach (var varSortNode in refSortNodeList) {
Console.WriteLine ("SortNode rating is {0}", varSortNode.m_valRating);
}