I have a list as below
I want to convert this into a list which looks like this
Can anybody suggest some sample code?
I have tried the bellow code
class Program
{
static void Main(string[] args)
{
var mockForDataColection = Mock.MockForDataColection();
Factory f = new Factory();
List<ResultSet> rl = new List<ResultSet>();
var groups = mockForDataColection.GroupBy(x => new { group1 = x.GroupIdOne, group2 = x.GroupIdTwo, group3 = x.GroupIdThree }).ToList();
f.Name = mockForDataColection.FirstOrDefault(c => c.Key == "Chamber").Value;
f.RunNumber = mockForDataColection.FirstOrDefault(c => c.Key == "RunNumber").Value;
var groupBy = mockForDataColection.GroupBy(c => c.GroupIdThree).Skip(1);
foreach (var dataCollection in groupBy)
{
ResultSet r = new ResultSet();
r.BarCode = dataCollection.FirstOrDefault(d => d.Key == "BarCode").Value;
r.IsPassed = dataCollection.FirstOrDefault(d => d.Key == "IsPassed").Value;
rl.Add(r);
}
f.ResultSet = rl;
}
}
public class DataCollection
{
public int GroupIdOne { get; set; }
public int GroupIdTwo { get; set; }
public int GroupIdThree { get; set; }
public string Key { get; set; }
public string Value { get; set; }
}
public class Factory
{
public string Name { get; set; }
public string RunNumber { get; set; }
public List<ResultSet> ResultSet { get; set; }
}
public class ResultSet
{
public string BarCode { get; set; }
public string IsPassed { get; set; }
public int FailiureCode { get; set; }
}
public static class Mock
{
public static List<DataCollection> MockForDataColection()
{
List<DataCollection> dataCollectionList = new List<DataCollection>();
DataCollection dataCollection = new DataCollection
{
GroupIdOne = 1,
GroupIdTwo = 1,
GroupIdThree = 0,
Key = "Chamber",
Value = "Test Chamber"
};
DataCollection dataCollection1 = new DataCollection
{
GroupIdOne = 1,
GroupIdTwo = 1,
GroupIdThree = 0,
Key = "RunNumber",
Value = "2"
};
DataCollection dataCollection2 = new DataCollection
{
GroupIdOne = 1,
GroupIdTwo = 2,
GroupIdThree = 3,
Key = "IsPassed",
Value = "P"
};
DataCollection dataCollection3 = new DataCollection
{
GroupIdOne = 1,
GroupIdTwo = 2,
GroupIdThree = 3,
Key = "BarCode",
Value = "PQWERT"
};
DataCollection dataCollection4 = new DataCollection
{
GroupIdOne = 1,
GroupIdTwo = 2,
GroupIdThree = 4,
Key = "IsPassed",
Value = "F"
};
DataCollection dataCollection5 = new DataCollection
{
GroupIdOne = 1,
GroupIdTwo = 2,
GroupIdThree = 4,
Key = "BarCode",
Value = "IUTYY"
};
dataCollectionList.Add(dataCollection);
dataCollectionList.Add(dataCollection1);
dataCollectionList.Add(dataCollection2);
dataCollectionList.Add(dataCollection3);
dataCollectionList.Add(dataCollection4);
dataCollectionList.Add(dataCollection5);
return dataCollectionList;
}
}
I think it's not a good code. Please suggest some other easy way to achieve this one.
Need to convert the data collection class into Factory class. In data, collection class has Key and Value Properties. Key is act as a property in Factory class Value is Value. Based on the GroupId Only we will decide it will go to Parent class (Factory) or child class (ResultSet).
GroupId One value is same means it all under a single entity. GroupId Two value differs means it is a related entity.
I have completely edited the answer, changed everything so that it is right and according to what was asked.
listA, your data to be grouped
var listA = new List<DataCollection>
{
new DataCollection { GroupIdOne = 1, GroupIdTwo = 1, GroupIdThree = 0, Key = "Chamber", Value = "Test Chamber" },
new DataCollection { GroupIdOne = 1, GroupIdTwo = 1, GroupIdThree = 0, Key = "RunNumber", Value = "2" },
new DataCollection { GroupIdOne = 1, GroupIdTwo = 2, GroupIdThree = 3, Key = "IsPassed", Value = "P" },
new DataCollection { GroupIdOne = 1, GroupIdTwo = 2, GroupIdThree = 3, Key = "BarCode", Value = "PQWERT" },
new DataCollection { GroupIdOne = 1, GroupIdTwo = 2, GroupIdThree = 4, Key = "IsPassed", Value = "F"},
new DataCollection { GroupIdOne = 1, GroupIdTwo = 2, GroupIdThree = 4, Key = "BarCode", Value = "IUTYY"}
};
listB
var listB = listA
.Where(x => x.Key.Contains("BarCode"))
.GroupBy(g => new {g.GroupIdOne, g.GroupIdTwo, g.GroupIdThree, g.Key, g.Value})
.Select(s =>
new ResultSet
{
BarCode = s.Key.Value,
IsPassed = listA.FirstOrDefault(a => a.Key.Equals("IsPassed")
&& a.GroupIdOne == s.Key.GroupIdOne
&& a.GroupIdTwo == s.Key.GroupIdTwo
&& a.GroupIdThree == s.Key.GroupIdThree
)?.Value ?? ""
})
.ToList();
Related
I have 2 list
IEnumerable<int> Ids, IEnumerable<Guid> GuidIds
for sample data
IEnumerable<int> ids1 = new List<int>() { 1, 2, 4 };
IEnumerable<Guid> guidIds = new List<Guid>() { new Guid("F44D7A64-8BDE-41E1-810F-B24377AD7F94"), new Guid("F44D7A64-8BDE-41E1-810F-B24377AD7F96"), new Guid("F44D7A64-8BDE-41E1-810F-B24377AD7F97") };
and a class
public class ClassEnd
{
public int Id { get; set; }
public Guid GuidId { get; set; }
}
I want to merge into this by Linq query
IEnumerable<ClassEnd> mergeList = new List<ClassEnd>()
{
new ClassEnd() { Id = 1, CompanyId = new Guid("F44D7A64-8BDE-41E1-810F-B24377AD7F94") },
new ClassEnd() { Id = 2, CompanyId = new Guid("F44D7A64-8BDE-41E1-810F-B24377AD7F96") },
new ClassEnd() { Id = 3, CompanyId = new Guid("F44D7A64-8BDE-41E1-810F-B24377AD7F97") }
};
Could you please help me with how to merge like the above "mergeList" by using Linq?
If lists are of the same size - it can be easily achieved with Enumerable.Zip:
var classEnds = ids1
.Zip(guidIds, (i, guid) => new ClassEnd
{
Id = i,
GuidId = guid
})
.ToList();
There is something that is not working, I cannot figured out...
I want to load data from a List. I have try several codes
MLContext mlContext = new MLContext();
var listData = new List<ProductEntry>
{
new ProductEntry {CoPurchaseProductID = 12, ProductID = 4},
new ProductEntry {CoPurchaseProductID = 12, ProductID = 3},
new ProductEntry {CoPurchaseProductID = 11, ProductID = 5},
new ProductEntry {CoPurchaseProductID = 11, ProductID = 3}
};
var data = mlContext.Data.LoadFromEnumerable(listData);
var options = new MatrixFactorizationTrainer.Options
{
MatrixColumnIndexColumnName = nameof(ProductEntry.ProductID),
MatrixRowIndexColumnName = nameof(ProductEntry.CoPurchaseProductID),
LabelColumnName = "Label",
LossFunction = MatrixFactorizationTrainer.LossFunctionType.SquareLossOneClass,
Alpha = 0.01,
Lambda = 0.025,
Quiet = false,
C = 0.00001,
ApproximationRank = 10,
NumberOfIterations = 20
};
var est = mlContext.Recommendation().Trainers.MatrixFactorization(options);
ITransformer model = est.Fit(data);
var predictionengine = mlContext.Model.CreatePredictionEngine<ProductEntry, Copurchase_prediction>(model);
Console.WriteLine("Calculating the top 3 products for product 3...");
var top5 = (from m in Enumerable.Range(1, 262111)
let p = predictionengine.Predict(
new ProductEntry()
{
ProductID = 3,
CoPurchaseProductID = (uint)m
})
orderby p.Score descending
select (ProductID: m, Score: p.Score)).Take(10);
foreach (var t in top5)
Console.WriteLine($" Score:{t.Score}\tProduct: {t.ProductID}");
Console.ReadKey();
I am getting a problem about a "Label"
This is the classes:
public class Copurchase_prediction
{
public float Score { get; set; }
}
public class ProductEntry
{
[KeyType(count: 262111)]
public float Label { get; set; }
[KeyType(count: 262111)]
public uint ProductID { get; set; }
[KeyType(count: 262111)]
public uint CoPurchaseProductID { get; set; }
}
Getting the error:
System.ArgumentOutOfRangeException: 'Member Label marked with KeyType attribute, but does not appear to be a valid kind of data for a key type (Parameter 'userType')'
Any idea?
Thanks guys!
Remove the [KeyType(count: 262111)] annotation for public float Label { get; set; } property
Label is not a key
So here I have some code, which works ok. But I want to change the select part to something else, I am not sure what other methods I can use any help would be appreciated.
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var all = new List<People>{new People{Id = 1, Name = "andy1", Age = null}, new People{Id = 2, Name = "andy2", Age = null}, new People{Id = 3, Name = "andy3", Age = null}, new People{Id = 4, Name = "andy4", Age = null}, };
var someOfThem = new List<People>{new People{Id = 1, Name = null, Age = 1}, new People{Id = 2, Name = null, Age = 1},new People{Id = 3, Name = null, Age = 1}};
var test = someOfThem.Select(c =>
{
c.Name = all.Find(a => a.Id == c.Id).Name;
return c;
});
foreach (var item in test)
Console.WriteLine("{0}={1}={2}", item.Id, item.Name, item.Age);
}
}
public class People
{
public int Id
{
get;
set;
}
public int? Age
{
get;
set;
}
public string Name
{
get;
set;
}
}
And here is the result.
1=andy1=1
2=andy2=1
3=andy3=1
I am just wondering is there another way to achieve the same result but a more elegant way? or an easier way?
var test = someOfThem.Select(c =>
{
c.Name = all.Find(a => a.Id == c.Id).Name;
return c;
});
Update
Sorry I did not show my problem properly at first, I have updated my quesiton. Please have a look again.
You can use C#'s LINQ keywords and more specifically, the join keyword assosciated with it:
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var all = new List<People> { new People { Id = 1, Name = "andy1", }, new People { Id = 2, Name = "andy2", }, new People { Id = 3, Name = "andy3", }, new People { Id = 4, Name = "andy4", }, };
var someOfThem = new List<People> { new People { Id = 1, Name = null, }, new People { Id = 2, Name = null, } };
var test = from item in someOfThem
join element in all on item.Id equals element.Id
select element;
foreach (var item in test)
Console.WriteLine("{0}={1}", item.Id, item.Name);
}
}
public class People
{
public int Id
{
get;
set;
}
public string Name
{
get;
set;
}
}
The code version would be
var test = someOfThem.Join(all, item => item.Id, element => element.Id, (item, element) => element);
as shown in Robert's comment
You can use the Join (you can also use a dictionary, but I'm not going to show it):
Here's the syntax for join:
var test = someOfThem.Join(all, item => item.Id, element => element.Id,
(item, element) => new Person {
Id = item.Id ?? element.Id,
Name = item.Name ?? element.Name,
Age = item.Age ?? element.Age
});
You can implement Equals and GetHashCode in your People class and use Intersect.
Or, create an EqualityComparer, that way your comparison logic is decoupled:
class Program
{
public static void Main()
{
var all = new List<People> { new People { Id = 1, Name = "andy1", }, new People { Id = 2, Name = "andy2", }, new People { Id = 3, Name = "andy3", }, new People { Id = 4, Name = "andy4", }, };
var someOfThem = new List<People> { new People { Id = 1, Name = null, }, new People { Id = 2, Name = null, } };
var test = all.Intersect(someOfThem, new PeopleIdComparer()).ToList();
foreach (var item in test)
Console.WriteLine("{0}={1}", item.Id, item.Name);
}
}
public class PeopleIdComparer : IEqualityComparer<People>
{
public bool Equals(People x, People y)
{
return x.Id == y.Id;
}
public int GetHashCode(People obj)
{
return HashCode.Combine(obj.Id);
}
}
public class People
{
public int Id
{
get;
set;
}
public string Name
{
get;
set;
}
}
I having the data structure
-Emp1 - Emp1_1 - Emp1_1_1
- Emp1_1_2
- Emp1_2 - Emp1_2_1
- Emp1_2_2
-Emp2 - Emp2_1 - Emp2_1_1
- Emp2_1_2
- Emp2_2 - Emp2_2_1
- Emp2_2_2
I want a dictionary which hold extreme leaf node as key and its highest parent as value.
OP:
(Emp1_1_1, Emp1)
(Emp1_1_2, Emp1)
(Emp1_2_1, Emp1)
(Emp1_2_2, Emp1)
(Emp2_1_1, Emp2)
(Emp2_1_2, Emp2)
(Emp2_2_1, Emp2)
(Emp2_2_2, Emp2)
(Emp1_1_1, Emp1)
(Emp1_1_2, Emp1)
(Emp1_2_1, Emp1)
(Emp1_2_2, Emp1)
(Emp2_1_1, Emp2)
(Emp2_1_2, Emp2)
(Emp2_2_1, Emp2)
(Emp2_2_2, Emp2)
Below is c# code
public class Program
{
public static void Main()
{
var program = new Program();
var empList = program.GetData();
//Some linq which return the expected dictionary.
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public int parentEmployee { get; set; }
public List<Employee> childList { get; set; }
}
List<Employee> GetData()
{
var empList = new List<Employee>();
var emp1 = new Employee() { Id = 1, Name = "Emp1_Name", childList = new List<Employee>() };
var emp1_1 = new Employee() { Id = 2, Name = "Emp1_1_Name", parentEmployee = emp1.Id, childList = new List<Employee>() };
var emp1_2 = new Employee() { Id = 3, Name = "Emp1_2_Name", parentEmployee = emp1.Id, childList = new List<Employee>() };
emp1.childList.Add(emp1_1);
emp1.childList.Add(emp1_2);
var emp1_1_1 = new Employee() { Id = 4, Name = "Emp1_1_1_Name", parentEmployee = emp1_1.Id };
var emp1_1_2 = new Employee() { Id = 5, Name = "Emp1_1_2_Name", parentEmployee = emp1_1.Id };
emp1_1.childList.Add(emp1_1_1);
emp1_1.childList.Add(emp1_1_2);
var emp1_2_1 = new Employee() { Id = 6, Name = "Emp1_2_1_Name", parentEmployee = emp1_2.Id };
var emp1_2_2 = new Employee() { Id = 7, Name = "Emp1_2_2_Name", parentEmployee = emp1_2.Id };
emp1_2.childList.Add(emp1_2_1);
emp1_2.childList.Add(emp1_2_2);
var emp2 = new Employee() { Id = 1, Name = "emp2_Name", childList = new List<Employee>() };
var emp2_1 = new Employee() { Id = 2, Name = "emp2_1_Name", parentEmployee = emp2.Id, childList = new List<Employee>() };
var emp2_2 = new Employee() { Id = 3, Name = "emp2_2_Name", parentEmployee = emp2.Id, childList = new List<Employee>() };
emp2.childList.Add(emp2_1);
emp2.childList.Add(emp2_2);
var emp2_1_1 = new Employee() { Id = 4, Name = "emp2_1_1_Name", parentEmployee = emp2_1.Id };
var emp2_1_2 = new Employee() { Id = 5, Name = "emp2_1_2_Name", parentEmployee = emp2_1.Id };
emp2_1.childList.Add(emp2_1_1);
emp2_1.childList.Add(emp2_1_2);
var emp2_2_1 = new Employee() { Id = 6, Name = "emp2_2_1_Name", parentEmployee = emp2_2.Id };
var emp2_2_2 = new Employee() { Id = 7, Name = "emp2_2_2_Name", parentEmployee = emp2_2.Id };
emp2_2.childList.Add(emp2_2_1);
emp2_2.childList.Add(emp2_2_2);
empList.Add(emp1);
empList.Add(emp2);
return empList;
}
}
I tried some solution like calling private self referencing function in linq,
But it works for a one parent - one child relation.
If the use of a recursive function is acceptable:
Func<IEnumerable<Employee>, IEnumerable<Employee>> flatten = null;
flatten = (IEnumerable<Employee> employees) =>
employees.SelectMany(c => c.childList != null ? flatten(c.childList) : Enumerable.Empty<Employee>()).Concat(employees);
var dict = (
from topNode in empList
from node in flatten(topNode.childList)
where node.childList == null || node.childList.Count == 0
select new KeyValuePair<string, string>(node.Name, topNode.Name)
).ToDictionary(kv => kv.Key, kv => kv.Value);
foreach(var keyValuePair in dict)
{
Console.WriteLine($"Key={keyValuePair.Key}, Value={keyValuePair.Value}");
}
This outputs:
Key=Emp1_1_1_Name, Value=Emp1_Name
Key=Emp1_1_2_Name, Value=Emp1_Name
Key=Emp1_2_1_Name, Value=Emp1_Name
Key=Emp1_2_2_Name, Value=Emp1_Name
Key=emp2_1_1_Name, Value=emp2_Name
Key=emp2_1_2_Name, Value=emp2_Name
Key=emp2_2_1_Name, Value=emp2_Name
Key=emp2_2_2_Name, Value=emp2_Name
try this
public static void Main()
{
var program = new Program();
var empList = program.GetData();
Func<IEnumerable<Employee>, Employee, Dictionary<Employee, Employee>> TreeToDict = null;
TreeToDict = (employees, topParent) =>
employees.SelectMany(e =>
{
if(e.childList != null)
{
return TreeToDict(e.childList, topParent == null ? e : topParent);
}
else
{
Dictionary<Employee, Employee> dict = new Dictionary<Employee, Employee>();
dict.Add(e, topParent == null ? e : topParent);
return dict;
}
}).ToDictionary(x => x.Key, x => x.Value);
foreach(var emp in TreeToDict (empList, null))
{
Console.WriteLine("key : {0}, value {1}", emp.Key.Name, emp.Value.Name);
}
}
result
key : Emp1_1_1_Name, value Emp1_Name
key : Emp1_1_2_Name, value Emp1_Name
key : Emp1_2_1_Name, value Emp1_Name
key : Emp1_2_2_Name, value Emp1_Name
key : emp2_1_1_Name, value emp2_Name
key : emp2_1_2_Name, value emp2_Name
key : emp2_2_1_Name, value emp2_Name
key : emp2_2_2_Name, value emp2_Name
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> ?