How to convert list item to multidimensional array in c#? - c#

I have a single list of data like
List 0 index Contains : BlockId = 438001,DistrictId = 438,TownId = 0,UserId = 1077
UserTypeId = 4,VillageId = 238047,ZoneId = 1018
List 1 index contains : BlockId = 438001,DistrictId = 438,TownId = 0,UserId = 1077,UserTypeId = 4,VillageId = 238048,ZoneId = 1018
List 2 index contains : BlockId = 438002,DistrictId = 438,TownId = 0,UserId = 1077,UserTypeId = 4,VillageId = 238138,ZoneId = 1018
And now I want to create a multidimensional array according to that like
public List<int>[][] arrayList{get;set;}
I need to convert list data to multidimensional array list like
[0]
[0] -> Count 1 -> 438001 --> Showing blockId
[1]-> Count 3 -> 238047,238048 --> showing villageId
[1]
[0]->count 1 -> 438002
[1]->count 2 -> 238138
[2]->count 3-> 0 --> showing townId
var data = user.getUserRolebyUserId(userId);
var blkList = data.GroupBy(x => x.BlockId);
List<int>[][] lst;
foreach (var item in data.GroupBy(x => x.BlockId))
{
List<int>[][] array = [item.Key,item.Select(x => x.VillageId).ToList(), item.Select(q => q.TownId)];
}
I am trying to applying this but it's showing me error for Invalid Expression.
So How can I convert list into multidimensional array ?

Use a Dictionary :
class Program
{
static void Main(string[] args)
{
List<Location> locations = new List<Location>() {
new Location() { BlockId = 438001,DistrictId = 438,TownId = 0,UserId = 1077, UserTypeId = 4,VillageId = 238047,ZoneId = 1018 },
new Location() { BlockId = 438001,DistrictId = 438,TownId = 0,UserId = 1077,UserTypeId = 4,VillageId = 238048,ZoneId = 1018},
new Location() { BlockId = 438002,DistrictId = 438,TownId = 0,UserId = 1077,UserTypeId = 4,VillageId = 238138,ZoneId = 1018 }
};
Dictionary<int, List<int>> dict = locations
.GroupBy(x => x.BlockId, y => y.Items)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
public class Location
{
public int BlockId { get; set; }
public int DistrictId { get; set; }
public int TownId { get; set; }
public int UserId { get; set; }
public int UserTypeId { get; set; }
public int VillageId { get; set; }
public int ZoneId { get; set; }
public List<int> Items {
get { return new List<int> { BlockId, DistrictId, TownId, UserId, UserTypeId, VillageId, ZoneId }; }
set {;}
}
}

Related

Convert List<string> to List<object> in C#

I have a list of string that looks something like this:
var rawData = new List<string>(){ "EUR/USD;123" , "EUR/GBP;321", "BTC/USD;2321"};
I have the following structure:
public class Data
{
public string instrument { get; set; }
public string positions { get; set; }
}
My goal is to have a list of the string data, splited on the ';' char and converted to a list of objects.
var processedData = new List<Data>();
// processedData[0] ( instrument = EUR/USD, positions = 123 )
// processedData[1] ( instrument = EUR/GBP, positions = 321)
// processedData[2] ( instrument = BTC/USD, positions = 2321)
Do you have any idea how can I do this ?
You can try Linq and query rawData:
var processedData = rawData
.Select(item => item.Split(';'))
.Select(items => new Data() {
instrument = items[0],
positions = items[1]
})
.ToList();
foreach(var rawString in rawData){
var split = rawString.Split(";");
processedData.Add(new Data(){
instruments = split[0],
positions = split[1]
});
}
You can try this code below
private static void TestFunc()
{
var rawData = new List<string>() { "EUR/USD;123", "EUR/GBP;321", "BTC/USD;2321" };
var processedData = new List<Data1>();
foreach (var item in rawData)
{
var ins = item.Split(";")[0];
var pos = item.Split(";")[1];
processedData.Add(new Data1(ins, pos));
}
}
you can use linq
void Main()
{
var rawData = new List<string>() { "EUR/USD;123", "EUR/GBP;321", "BTC/USD;2321" };
rawData.Select(s =>
new Data() {instrument= s.Split(";")[0],positions = (s.Split(";").Count() > 1) ? s.Split(";")[1] : null})
.ToList().Dump();
}
public class Data
{
public string instrument { get; set; }
public string positions { get; set; }
}

How to use linq to "flatten" an hierachy?

Given the following code example, how do I:
Get the commented out lines in the unfiltered list to work (without changing the definition of Result)?
Get the commented out lines in the filtered list to work (without changing the definition of Result)? From my maths it should give 32 records. Hopefully my output intent is clear enough for others to understand
Any questions feel free to ask
Regards
Kyle
//Populate data
var alphas = new List<Alpha>();
for (int a = 1; a <= 10; a++)
{
var alpha = new Alpha() { Id = a, Name = "A" + a };
for (int b = 1; b <= 10; b++)
{
var beta = new Beta() { Id = b, Name = "B" + b };
for (int c = 1; c <= 10; c++)
{
var charlie = new Charlie() { Id = c, Name = "C" + c };
for (int d = 1; d <= 10; d++)
{
var delta = new Delta() { Id = d, Name = "D" + d };
charlie.Deltas.Add(delta);
}
beta.Charlies.Add(charlie);
}
alpha.Betas.Add(beta);
}
alphas.Add(alpha);
}
//Get results into required format without filtering
var unfilteredResults = alphas.Select(a => new Result
{
AId = a.Id,
AName = a.Name,
//BId = a.Betas.Select(b => b.Id),
//BName = a.Betas.Select(b => b.Name),
//CId = a.Betas.Select(b => b.Charlies.Select(c => c.Id)),
//CName = a.Betas.Select(b => b.Charlies.Select(c => c.Name)),
//DId = a.Betas.Select(b => b.Charlies.Select(c => c.Deltas.Select(d => d.Id))),
//DName = a.Betas.Select(b => b.Charlies.Select(c => c.Deltas.Select(d => d.Name)))
});
var whiteListAIds = new List<int>() { 1, 2 };
var whiteListBIds = new List<int>() { 3, 4 };
var whiteListCIds = new List<int>() { 5, 6 };
var whiteListDIds = new List<int>() { 7, 8 };
//Get results into required format with filtering
var filteredResults = alphas.Where(a => whiteListAIds.Contains(a.Id)).Select(a => new Result
{
AId = a.Id,
AName = a.Name,
//BId = a.Betas.Where(b => whiteListBIds.Contains(b.Id)).Select(b => b.Id),
//BName = a.Betas.Where(b => whiteListBIds.Contains(b.Id)).Select(b => b.Name),
//CId = a.Betas.Where(b => whiteListBIds.Contains(b.Id)).Select(b => b.Charlies.Where(c => whiteListCIds.Contains(c.Id)).Select(c => c.Id)),
//CName = a.Betas.Where(b => whiteListBIds.Contains(b.Id)).Select(b => b.Charlies.Where(c => whiteListCIds.Contains(c.Id)).Select(c => c.Name)),
//DId = a.Betas.Where(b => whiteListBIds.Contains(b.Id)).Select(b => b.Charlies.Where(c => whiteListCIds.Contains(c.Id)).Select(c => c.Deltas.Where(d => whiteListDIds.Contains(d.Id)).Select(d => d.Id))),
//DName = a.Betas.Where(b => whiteListBIds.Contains(b.Id)).Select(b => b.Charlies.Where(c => whiteListCIds.Contains(c.Id)).Select(c => c.Deltas.Where(d => whiteListDIds.Contains(d.Id)).Select(d => d.Name)))
});
class Alpha
{
public int Id { get; set; }
public string Name { get; set; }
public List<Beta> Betas { get; set; } = new List<Beta>();
}
class Beta
{
public int Id { get; set; }
public string Name { get; set; }
public List<Charlie> Charlies { get; set; } = new List<Charlie>();
}
class Charlie
{
public int Id { get; set; }
public string Name { get; set; }
public List<Delta> Deltas { get; set; } = new List<Delta>();
}
class Delta
{
public int Id { get; set; }
public string Name { get; set; }
}
class Result
{
public int AId { get; set; }
public string AName { get; set; }
public int BId { get; set; }
public string BName { get; set; }
public int CId { get; set; }
public string CName { get; set; }
public int DId { get; set; }
public string DName { get; set; }
}
Got it working as below thanks to the first answer linq selectmany flatten multiple levels
Basically had to combine .SelectMany() on the "outer" parents and .Select() on the last/inner child.
//Populate data
var alphas = new List<Alpha>();
for (int a = 1; a <= 10; a++)
{
var alpha = new Alpha() { Id = a, Name = "A" + a };
for (int b = 1; b <= 10; b++)
{
var beta = new Beta() { Id = b, Name = "B" + b };
for (int c = 1; c <= 10; c++)
{
var charlie = new Charlie() { Id = c, Name = "C" + c };
for (int d = 1; d <= 10; d++)
{
var delta = new Delta() { Id = d, Name = "D" + d };
charlie.Deltas.Add(delta);
}
beta.Charlies.Add(charlie);
}
alpha.Betas.Add(beta);
}
alphas.Add(alpha);
}
var unfilteredResults = alphas.SelectMany(a => a.Betas.SelectMany(b=> b.Charlies.SelectMany(c=> c.Deltas.Select(d => new Result
{
AId = a.Id,
AName = a.Name,
BId = b.Id,
BName = b.Name,
CId = c.Id,
CName = c.Name,
DId = d.Id,
DName = d.Name
}))));
var whiteListAIds = new List<int>() { 1, 2 };
var whiteListBIds = new List<int>() { 3, 4 };
var whiteListCIds = new List<int>() { 5, 6 };
var whiteListDIds = new List<int>() { 7, 8 };
//Get results into required format with filtering
var filteredResults = unfilteredResults.Where(r => whiteListAIds.Contains(r.AId) && whiteListBIds.Contains(r.BId) && whiteListCIds.Contains(r.CId) && whiteListDIds.Contains(r.DId));
Console.WriteLine("Finished");
class Alpha
{
public int Id { get; set; }
public string Name { get; set; }
public List<Beta> Betas { get; set; } = new List<Beta>();
}
class Beta
{
public int Id { get; set; }
public string Name { get; set; }
public List<Charlie> Charlies { get; set; } = new List<Charlie>();
}
class Charlie
{
public int Id { get; set; }
public string Name { get; set; }
public List<Delta> Deltas { get; set; } = new List<Delta>();
}
class Delta
{
public int Id { get; set; }
public string Name { get; set; }
}
class Result
{
public int AId { get; set; }
public string AName { get; set; }
public int BId { get; set; }
public string BName { get; set; }
public int CId { get; set; }
public string CName { get; set; }
public int DId { get; set; }
public string DName { get; set; }
}

How to aggregate data, pass and fail as final result?

I have a list of result either having or not having Data plus has Pass and Fail like below,
var results = new List<Result>
{
new Result{Data = new Data{Name = "A"}, Pass = 1, Fail = 0},
new Result{Data = new Data{Name = "B"}, Pass = 3, Fail = 1},
new Result{Pass = 1, Fail = 0}
};
I need to aggregate data and need this as final result output,
var finalResult = new FinalResult
{
Datas = new List<Data> { new Data { Name = "A" }, new Data { Name = "B" } },
TotalPass = 5,
TotalFail = 1,
Divident = 5/1
}
I tried something like below, but totalPass and totalfail, are not coming correct. Plus, how to aggregate Data?
int totalPass = 0;
int totalfail = 0;
var finalResult = new FinalResult();
foreach (var r in results)
{
totalPass += r.Pass;
totalfail += r.Fail;
}
finalResult.TotalFail = totalPass;
finalResult.TotalFail = totalfail;
finalResult.Divident = totalPass / totalfail;
Here are the two classes:
public class FinalResult
{
public List<Data> Datas { get; set; }
public int TotalPass { get; set; }
public int TotalFail { get; set; }
public int Divident { get; set; }
}
public class Result
{
public Data Data { get; set; }
public int Pass { get; set; }
public int Fail { get; set; }
}
public class Data
{
public string Name { get; set; }
}
You can achieve this easily using LINQ:
var finalResult = new FinalResult
{
Datas = results.Where(r => r.Data != null).Select(r => r.Data).ToList(),
TotalPass = results.Sum(r => r.Pass),
TotalFail = results.Sum(r => r.Fail)
};
// Beware of division by zero and integer division.
finalResult.Divident = finalResult.TotalPass / finalResult.TotalFail;
Notes:
You should probably check the value of TotalFail before the division to prevent division by zero.
As Groo mentioned in the comments, Divident should probably be declared as double and you should cast one of the parts to double unless you do want Integer Division.

Linq counting second grouping and counting without grouping

I'm trying to build a summary query that i will be using for statistics.
i have a dataTable with the folowing columns (approx 18000 rows) :
Artist / Album / file_path (one for each song) / rating /
each artist has 1 or several album with has songs and each songs have a rating
I want to have the following result :
For each artist ID (more reliable than the artist name), the total number of albums, the total number of songs, and the total number of ratings equal to 5.
Artist x / #album / #songs / #rating = 5 / song.first() //in song.first i have access to the file path, it can be any file path from the artist hence the first one.
I've been pulling my hair for several hours now and i cannot manage to get the # of albums per artist :( This is what i've been trying so far :
i have a Class for the query :
public class art_detail
{
public string artiste { get; set; }
public string fp { get; set; } // the file_path
public int nbr_album { get; set; }
public int nbr_song { get; set; }
public int nbr_rat5 { get; set; }
}
this is the query i came up to :
var result = from res in Globals.ds.Tables[0].AsEnumerable() // the table
.GroupBy(x => new { art = x.Field<int>("Artist_ID"), alb = x.Field<string>("album") })
.Select(x => new art_detail { artiste = x.Select(p =>p.Field<string>("artiste")).First(), fp = x.Select(p=>p.Field<string>("file_path")).First(), nbr_album = x.Key.alb.Count() })
.OrderBy(x => x.artiste)
select res;
The count is unfortunately completely wrong and i have no idea how to get the # of rating = 5 :(
Thanks for the help !
Edit :
Here is my query to make it work :
var table = Globals.ds.Tables[0].AsEnumerable();
var stats = table.GroupBy(x => x.Field<int>("Artist_ID"))
.Select(x => new art_detail
{
artiste = x.Select(p=>p.Field<string>("artiste")).First(),
nbr_album = x.Select(y => y.Field<string>("album")).Distinct().Count(),
fp = x.Select(y => y.Field<string>("file_path")).FirstOrDefault(),
nbr_song = x.Count(),
nbr_rat5 = x.Count(y => y.Field<int>("Rating") == 5)
});
Simpler than what i thought :)
Assuming a table whose schema matches this class:
public class Song
{
public string ArtistID { get; set; }
public string Album { get; set; }
public string FilePath { get; set; }
public int Rating { get; set; }
}
and given a LINQ source, you have the following query:
IQueryable<Song> table = /*insert source*/;
var stats = table.GroupBy(x => x.ArtistID);
.Select(x => new art_detail
{
artiste = x.Key,
nbr_album = x.Select(y => y.Album).Distinct().Count(),
nbr_song = x.Count(),
nbr_rat5 = x.Count(y => y.Rating == 5),
});
I used head compiled query as it seemed more understandable for me in this case:
Example model:
public class Artist
{
public string ArtistID { get; set; }
public string Album { get; set; }
public string FilePath { get; set; }
public int Rating { get; set; }
public int NumberOfSongs { get; set; }
}
Creating some dummy records for Usher and Beyonce:
//Usher
var artistOne = new Artist()
{
ArtistID = "Usher",
Album = "Lit",
FilePath = "dummy/path/here",
Rating = 5,
NumberOfSongs = 9
};
var artistTwo = new Artist()
{
ArtistID = "Usher",
Album = "Sick",
FilePath = "dummy/path/here",
Rating = 5,
NumberOfSongs = 11
};
var artistThree = new Artist()
{
ArtistID = "Usher",
Album = "Dope",
FilePath = "dummy/path/here",
Rating = 4,
NumberOfSongs = 14
};
//Beyonce
var artistFour = new Artist()
{
ArtistID = "Beyonce",
Album = "Hot",
FilePath = "dummy/path/here",
Rating = 5,
NumberOfSongs = 8
};
var artistFive = new Artist()
{
ArtistID = "Beyonce",
Album = "Fire",
FilePath = "dummy/path/here",
Rating = 4,
NumberOfSongs = 16
};
var listOfArtist = new List<Artist> { artistOne, artistTwo, artistThree, artistFour, artistFive };
Running query:
var result = from a in listOfArtist
where a.Rating == 5
group a by a.ArtistID into art
select new
{
artist = art.Key,
numberOfAlbums = art.Count(),
numberOfSongs = art.Sum(d => d.NumberOfSongs),
};
Results:
Hope this helps =)

Select Max value from sublist with LINQ

How to write a LINQ query that would return row of type "Value" with Max Date and Max value for that date. it should be the row where name = "Correct"
I've written a query at the end, and it working, just trying to find a correct way of doing this.
Thanks in advance
public class MeasurePoint
{
public int No { get; set; }
public string Weight { get; set; }
public List<Values> Vals { get; set; }
}
public class Values
{
public string Name { get; set; }
public int Val { get; set; }
public DateTime Date { get; set; }
}
public static class Test
{
public static void Calc()
{
var mps = new List<MeasurePoint>();
mps.Add(new MeasurePoint()
{
No = 1,
Vals = new List<Values>()
{
new Values(){Date = DateTime.Now.Date.AddDays(1), Name = "testas", Val = 1},
new Values(){Date = DateTime.Now.Date.AddDays(2), Name = "testas", Val = 5},
new Values(){Date = DateTime.Now.Date, Name = "testas", Val = 15}
}});
mps.Add(new MeasurePoint()
{
No = 2,
Vals = new List<Values>()
{
new Values(){Date = DateTime.Now.Date, Name = "testas", Val = 11},
new Values(){Date = DateTime.Now.Date.AddDays(2), Name = "Correct", Val = 55},
new Values(){Date = DateTime.Now.Date, Name = "testas", Val = 15}
}
});
mps.Add(new MeasurePoint()
{
No = 3,
Vals = new List<Values>()
{
new Values(){Date = DateTime.Now.Date.AddDays(1), Name = "testas", Val = 111},
new Values(){Date = DateTime.Now.Date.AddDays(2), Name = "testas", Val = 52},
new Values(){Date = DateTime.Now.Date, Name = "testas", Val = 15}
}
});
mps.Add(new MeasurePoint()
{
No = 4,
Vals = new List<Values>()
});
var x = mps.ElementAt(0).Vals.Union(mps.ElementAt(1).Vals).Union(mps.ElementAt(2).Vals);
var z = x.Where(p => p.Date == x.Max(d => d.Date)).MaxBy(t=>t.Val);
//One more way I've found
var ttt = mps.SelectMany(p => p.Vals).GroupBy(t=>t.Date).MaxBy(r=>r.Key).MaxBy(g=>g.Val);
}
var max = mps.SelectMany(x => x.Vals)
.Aggregate((a, x) => (x.Date > a.Date) ||
((x.Date == a.Date) && (x.Val > a.Val)) ? x : a);
try this
var result = mps.Where(m => m.Vals.Count > 0)
.SelectMany(m => m.Vals
.OrderByDescending(v => v.Date)
.Take(1), (m, v) => new {m.No, v.Date, v.Name, v.Val});
EDIT - this is a new version as issue has become more clear
var result = mps.Where(m => m.Vals.Count > 0)
.SelectMany(m => m.Vals)
.OrderByDescending(v => v.Date)
.ThenByDescending(v => v.Val).Take(1);
How can use call MaxBy() if it's a method of IObservable<T> meanwhile GroupBy() returns IEnumerable<T> ?

Categories

Resources