I have this LINQ statement that tries to set the 1st element in the collection of string[]. But it doesn't work.
Below is the LINQ statement.
docSpcItem.Where(x => x.DocID == 2146943)
.FirstOrDefault()
.FinishingOptionsDesc[0] = "new value";
public string[] FinishingOptionsDesc
{
get
{
if (this._FinishingOptionsDesc != null)
{
return (string[])this._FinishingOptionsDesc.ToArray(typeof(string));
}
return null;
}
set { this._FinishingOptionsDesc = new ArrayList(value); }
}
What's wrong with my LINQ statement above?
Couple of things.. There are some problems with your get and set. I would just use auto properties like this..
public class DocSpcItem
{
public string[] FinishingOptionsDesc { get; set; }
public int DocID { get; set; }
}
Next for your linq statement, depending on the presence of an item with an id of 2146943 you might be setting a new version of the object rather than the one you intended. This should work..
[TestMethod]
public void Linq()
{
var items = new List<DocSpcItem>();
//2146943
for (var i = 2146930; i <= 2146950; i++)
{
items.Add(new DocSpcItem()
{ DocID = i
, FinishingOptionsDesc = new string[]
{ i.ToString() }
}
);
}
var item = items.FirstOrDefault(i => i.DocID == 2146943);
if (item != null)
{
item.FinishingOptionsDesc = new string[]{"The New Value"};
}
}
and
public class DocSpcItem
{
public string[] FinishingOptionsDesc { get; set; }
public int DocID { get; set; }
}
Related
I have a dictionary where values are stored in the following format -
userID, empDetails
For example,
1234, 'empName,jobDesc,CardNumber,Type'
I have to compare this information with another set of information such that -
If entered userId is present in the above dictionary, then remove this record from the dictionary.
If entered CardNumber is present (here userId is not known) in the above dictionary, then remove this record from the dictionary.
The first condition is simple and can be done by
dictionary.Remove(key)
But I am confused as to how would I implement the second condition. I want something like
if(CardNumber.PresentinAboveDictionary)
then
Remove that record
I know we can compare a partial string in a key like this, but I want to remove the record.
Check if any part of a hashtable value contains certain string c#
Assuming the employment details in your dictionary are a string in the specified format you would need to:
Search the values within the dictionary
Parse/Split the values to get the card numbers
Check the card numbers to see if they match the card number you are checking
Return the key value pair when a match occurs
Remove the entry for the key in the returned key value pair
Example code for the solution:
var dictionary = new Dictionary<int, string>() { { 1, "empName,jobDesc,124124134,Type" } };
var cardNumber = 124124134;
var entry = dictionary.FirstOrDefault(x => DoEmploymentDetailsContainCardNumber(x.Value, cardNumber));
if (!entry.Equals(default(KeyValuePair<int, string>)))
{
dictionary.Remove(entry.Key);
}
Method that checks if card number is present in employment details:
private static bool DoEmploymentDetailsContainCardNumber(string empDetails, int cardNumber)
{
var splitEmpDetails = empDetails.Split(',');
var empDetailsCardNumber = splitEmpDetails[2];
return empDetailsCardNumber == cardNumber.ToString();
}
Instead of Dictionary you can use a strongly typed List
Use the Linq builtin Remove method
Use Parallel.ForEach, iterate the list and remove the item (beware, takes more time)
pseudo code:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
using System.Collections;
namespace ConsoleApp4
{
public class Employee
{
public Employee(int userID, string empDetails)
{
string[] props = empDetails.Split(new char[] { ',' }, StringSplitOptions.None);
this.userID = userID;
this.empName = props[0];
this.jobDesc = props[1];
this.CardNumber = props[2];
this.Type = props[3];
}
public int userID { get; set; }
public string empName { get; set; }
public string jobDesc { get; set; }
public string CardNumber { get; set; }
public string Type { get; set; }
}
public class MyCustomList : List<Employee>
{
public void Add(int userID, string empDetails)
{
this.Add(new Employee(userID, empDetails));
}
public bool Remove(string CardNumber)
{
bool found = false ;
Parallel.ForEach(this,
(i, state) =>
{
if (i.CardNumber == CardNumber)
{
this.Remove(i);
state.Break();
}
});
return found;
}
public bool RemoveV2(string CardNumber)
{
bool found = false;
if (this.Any(x => x.CardNumber == CardNumber))
{
this.Remove(this.Where(x => x.CardNumber == CardNumber).First());
found = true;
}
return found;
}
}
class Program
{
static void Main(string[] args)
{
var dict = new MyCustomList();//userID, empDetails list
dict.Add(12341, "empName1,jobDesc,CardNumber1,Type");
dict.Add(12342, "empName2,jobDesc,CardNumber2,Type");
dict.Add(12343, "empName3,jobDesc,CardNumber3,Type");
dict.Add(12344, "empName4,jobDesc,CardNumber4,Type");
dict.Add(12345, "empName5,jobDesc,CardNumber5,Type");
dict.Add(12346, "empName6,jobDesc,CardNumber6,Type");
dict.Add(12347, "empName7,jobDesc,CardNumber7,Type");
dict.Add(12348, "empName8,jobDesc,CardNumber8,Type");
//remove CardNumber5
dict.Remove("CardNumber5");
Console.Write(dict);
}
}
}
you can follow the simple approach to remove the key by using a loop here.
Here I am assuming that there is no key with a value of -1 in the dictionary.
int keyToRemove = -1;
foreach (var entry in dictionary)
{
if (entry.Value.Contains(CardNumber))
{
keyToRemove = entry.Key;
break;
}
}
if (keyToRemove != -1)
{
dictionary.Remove(keyToRemove);
}
This is possibly overkill and is not optimised for reading the full dataset repeatedly but it is considerably faster than the accepted solution. I put together a test of the solution below which did the following:
Generated 1,000,000 data rows with unique IDs and card numbers (the solution would also work if the card numbers were not unique)
Randomly removed 100,000 data items by ID and 100,000 data items by card number
Generated a list of the remaining data items
The process took around 75 seconds.
I then tried to repeat steps 1) and 2) using the accepted answer - after around 10 minutes it's about 7% of the way through removing data items. Therefore I think the solution below is around 2 orders of magnitude faster for this type of operation.
There are probably better doubley linked list implementations out there but I am not too familiar with any of them.
namespace Question
{
public class EmployeeCollection
{
private readonly Dictionary<int, ListNode<EmployeeDetails>> _idDictionary = new();
private readonly Dictionary<string, Dictionary<int, EmployeeDetails>> _cardNumberDictionary = new();
private readonly LinkedList<EmployeeDetails> _list = new();
public void AddEmployee(EmployeeDetails details)
{
var node = new ListNode<EmployeeDetails>(details);
_list.AddToStart(node);
_idDictionary.Add(details.Id, node);
if(!_cardNumberDictionary.ContainsKey(details.CardNumber))
{
_cardNumberDictionary.Add(details.CardNumber, new Dictionary<int, EmployeeDetails>());
}
_cardNumberDictionary[details.CardNumber].Add(details.Id, details);
}
public void RemoveById(int id)
{
if (_idDictionary.TryGetValue(id, out var node))
{
_idDictionary.Remove(id);
_list.Remove(node);
var list = _cardNumberDictionary[node.Value.CardNumber];
list.Remove(id);
if(list.Count == 0)
{
_cardNumberDictionary.Remove(node.Value.CardNumber);
}
}
}
public void RemoveByCardNumber(string cardNumber)
{
if (_cardNumberDictionary.TryGetValue(cardNumber, out var employees))
{
_cardNumberDictionary.Remove(cardNumber);
foreach (var employee in employees)
{
if (_idDictionary.TryGetValue(employee.Key, out var node))
{
_list.Remove(node);
}
}
}
}
public IEnumerable<EmployeeDetails> Employees => _list.GetAllValues();
public EmployeeDetails? GetById(int id)
{
if(_idDictionary.ContainsKey(id))
{
return _idDictionary[id].Value;
}
return null;
}
}
public class EmployeeDetails
{
public int Id { get; init; }
public string Name { get; init; }
public string JobDescription { get; init; }
public string CardNumber { get; init; }
public string Type { get; init; }
public static EmployeeDetails FromData(int id, string details)
{
var parts = details.Split(',');
return new EmployeeDetails
{
Id = id,
Name = parts[0],
JobDescription = parts[1],
CardNumber = parts[2],
Type = parts[3],
};
}
}
public class LinkedList<T>
{
public int Count { get; private set; }
private ListNode<T>? Start { get; set; }
private ListNode<T>? End { get; set; }
public bool IsEmpty => Count == 0;
public void AddToStart(ListNode<T> node)
{
ArgumentNullException.ThrowIfNull(nameof(node));
node.Next = null;
node.Previous = null;
if (IsEmpty)
{
Start = End = node;
}
else
{
Start!.Previous = node;
node.Next = Start;
Start = node;
}
Count++;
}
public void Remove(ListNode<T> node)
{
if (node != Start)
{
node.Previous!.Next = node.Next;
}
else
{
Start = node.Next;
}
if (node != End)
{
node.Next!.Previous = node.Previous;
}
else
{
End = node.Previous;
}
Count--;
}
public IEnumerable<T> GetAllValues()
{
var counter = Start;
while (counter != null)
{
yield return counter.Value;
counter = counter.Next;
}
}
}
public class ListNode<T>
{
public T Value { get; }
public ListNode<T>? Previous { get; set; }
public ListNode<T>? Next { get; set; }
public ListNode(T value)
{
Value = value;
}
}
}
you can do something like this.
var recordsToRemove = dictionary.Where(x => x.Value.Contains("what you are looking for"))
.ToList();
if (recordsToRemove.Any())
{
foreach (var record in recordsToRemove)
{
dictionary.Remove(record.Key);
}
}
i have table looks like below
ID | Reason | PrID
-----------------
1 abc null
2 dhe null
3 aerc 1
4 dwes 2
5 adfje 1
i have class
public class Reason
{
public int Id { get; set; }
public string Reson{ get; set; }
public List<SecondryReason> SecReason{ get; set; }
public int? PrimaryId { get; set; }
}
public class SecondryReason
{
public int Id { get; set; }
public string Reason { get; set; }
public int PrimaryReasonId { get; set; }
}
I want this to be displayed in hierarchy level
if the prid is Null need to treat this as the parent remaining all child
i am trying Linq and unable to achieve this
Suggest me how to do this in an easy way in linq
So: You have a list/enumerable of type , whereof the SecReason List property is null. Then, using linq you want a list, were the only the "root" reasons remain, but the Sub-reasons got put in the lists, but as type SecondaryReason?
If so, I found this way to do it (linq and foreach):
static IEnumerable<Reason> GetReasonsGrouped(List<Reason> reasons)
{
var result = reasons.Where(x => x.PrimaryId == null);
foreach (var item in result)
{
item.SecReason = reasons.Where(x => x.PrimaryId == item.Id)
.Select(x => new SecondryReason()
{ Id = x.Id,
ReasonName = x.ReasonName,
PrimaryReasonId = item.Id
})
.ToList();
}
return result;
}
Or just linq, but harder to read:
var result = reasons.Where(x => x.PrimaryId == null)
.Select(x =>
{
x.SecReason = reasons.Where(r => x.PrimaryId == x.Id)
.Select(r => new SecondryReason()
{
Id = r.Id,
ReasonName = x.ReasonName,
PrimaryReasonId = x.Id
})
.ToList();
return x;
});
Not sure if linq will be the best solution, here is my proposed changes and method to get an Hierarchy type:
public class Reason
{
public int Id { get; set; }
public string Reson { get; set; }
public List<Reason> SecReason { get; set; }
public int? PrimaryId { get; set; }
//Adds child to this reason object or any of its children/grandchildren/... identified by primaryId
public bool addChild(int primaryId, Reason newChildNode)
{
if (Id.Equals(primaryId))
{
addChild(newChildNode);
return true;
}
else
{
if (SecReason != null)
{
foreach (Reason child in SecReason)
{
if (child.addChild(primaryId, newChildNode))
return true;
}
}
}
return false;
}
public void addChild(Reason child)
{
if (SecReason == null) SecReason = new List<Reason>();
SecReason.Add(child);
}
}
private List<Reason> GetReasonsHierarchy(List<Reason> reasons)
{
List<Reason> reasonsHierarchy = new List<Reason>();
foreach (Reason r in reasons)
{
bool parentFound = false;
if (r.PrimaryId != null)
{
foreach (Reason parent in reasonsHierarchy)
{
parentFound = parent.addChild(r.PrimaryId.Value, r);
if (parentFound) break;
}
}
if (!parentFound) reasonsHierarchy.Add(r);
}
return reasonsHierarchy;
}
I am working with some code that uses Columns.Add in conjunction with a lambda expression and would like to understand why/how it works. Here is a code snippet:
public ReportGrid(List<ReportRowDataContract> items)
: base(items)
{
if (items[0].ReportData1 != null)
{
if (items[0].ReportData1.DecimalValue != null)
{
Columns.Add(m => m.ReportData1.DecimalValue).Titled(items[0].ReportData1.Name).Encoded(false).
Sanitized(false).RenderValueAs(
m => (string.IsNullOrEmpty(#m.ReportData1.DisplayFormat)) ? Convert.ToDecimal(#m.ReportData1.DecimalValue).ToString("N") : Convert.ToDecimal(#m.ReportData1.DecimalValue).ToString(#m.ReportData1.DisplayFormat));
if (items[0].ReportData1.SumValue || items[0].ReportData1.AvgValue)
{
displaySummary = true;
SummaryData.Add(
new ReportDataDataContract
{
Name = items[0].ReportData1.Name,
AvgValue = items[0].ReportData1.AvgValue,
DecimalValue = 0
});
}
}
else if (items[0].ReportData1.IntValue != null)
{
Columns.Add(m => m.ReportData1.IntValue).Titled(items[0].ReportData1.Name);
if (items[0].ReportData1.SumValue || items[0].ReportData1.AvgValue)
{
displaySummary = true;
SummaryData.Add(
new ReportDataDataContract
{
Name = items[0].ReportData1.Name,
AvgValue = items[0].ReportData1.AvgValue,
IntValue = 0
});
}
}
else
{
Columns.Add(m => m.ReportData1.StringValue).Titled(items[0].ReportData1.Name);
}
}
if (items[0].ReportData2 != null)
{
if (items[0].ReportData2.DecimalValue != null)
{
Columns.Add(m => m.ReportData2.DecimalValue).Titled(items[0].ReportData2.Name).Encoded(false).
Sanitized(false).RenderValueAs(
m => (string.IsNullOrEmpty(#m.ReportData2.DisplayFormat)) ? Convert.ToDecimal(#m.ReportData2.DecimalValue).ToString("N") : Convert.ToDecimal(#m.ReportData2.DecimalValue).ToString(#m.ReportData1.DisplayFormat));
if (items[0].ReportData2.SumValue || items[0].ReportData2.AvgValue)
{
displaySummary = true;
SummaryData.Add(
new ReportDataDataContract
{
Name = items[0].ReportData2.Name,
AvgValue = items[0].ReportData2.AvgValue,
DecimalValue = 0
});
}
}
else if (items[0].ReportData2.IntValue != null)
{
Columns.Add(m => m.ReportData2.IntValue).Titled(items[0].ReportData2.Name);
if (items[0].ReportData2.SumValue || items[0].ReportData2.AvgValue)
{
displaySummary = true;
SummaryData.Add(
new ReportDataDataContract
{
Name = items[0].ReportData2.Name,
AvgValue = items[0].ReportData2.AvgValue,
IntValue = 0
});
}
}
else
{
Columns.Add(m => m.ReportData2.StringValue).Titled(items[0].ReportData2.Name);
}
}
This method consists of code that repeats itself out to ReportData6, changing only the ReportData field name with each repetition.
Here is the ReportRowDataContract class:
public class ReportRowDataContract
{
public ReportDataDataContract ReportData1 { get; set; }
public ReportDataDataContract ReportData2 { get; set; }
public ReportDataDataContract ReportData3 { get; set; }
public ReportDataDataContract ReportData4 { get; set; }
public ReportDataDataContract ReportData5 { get; set; }
public ReportDataDataContract ReportData6 { get; set; }
// an indexed property - for accessing report data fields by index
public ReportDataDataContract this[int i]
{
get
{
return new ReportDataDataContract[]
{
ReportData1,
ReportData2,
ReportData3,
ReportData4,
ReportData5,
ReportData6
}[i];
}
}
public int GetReportDataFieldCount()
{
return 6;
}
}
Unfortunately, I cannot change the structure of this class so I'm trying to convert the first code block into a method that loops. However, I'm stuck on what the Columns.Add is actually adding to.
Here is my code thus far:
public ReportGrid(List<ReportRowDataContract> items)
: base(items)
{
// get count of how many fields exist in ReportRowDataContract
int reportDataFieldCount = (new ReportRowDataContract()).GetReportDataFieldCount();
// create columns for grid for each field in ReportRowDataContract
//foreach (ReportRowDataContract item in items)
//{
int i = 0;
while (i < reportDataFieldCount)
{
AddGridColumn(items[0][i]);
i++;
}
//}
}
private void AddGridColumn(ReportDataDataContract reportColumn)
{
if (reportColumn != null)
{
if (reportColumn.DecimalValue != null)
{
Columns.Add(m => m.ReportData1.DecimalValue).Titled(reportColumn.Name).Encoded(false).
Sanitized(false).RenderValueAs(
m => (string.IsNullOrEmpty(#m.ReportData1.DisplayFormat)) ?
Convert.ToDecimal(#m.ReportData1.DecimalValue).ToString("N") :
Convert.ToDecimal(#m.ReportData1.DecimalValue).ToString(#m.ReportData1.DisplayFormat));
if (reportColumn.SumValue || reportColumn.AvgValue)
{
displaySummary = true;
SummaryData.Add(
new ReportDataDataContract
{
Name = reportColumn.Name,
AvgValue = reportColumn.AvgValue,
DecimalValue = 0
});
}
}
else if (reportColumn.IntValue != null)
{
Columns.Add(m => m.ReportData1.IntValue).Titled(reportColumn.Name);
if (reportColumn.SumValue || reportColumn.AvgValue)
{
displaySummary = true;
SummaryData.Add(
new ReportDataDataContract
{
Name = reportColumn.Name,
AvgValue = reportColumn.AvgValue,
IntValue = 0
});
}
}
else
{
Columns.Add(m => m.ReportData1.StringValue).Titled(reportColumn.Name);
}
}
}
In the AddGridColumn method the part that is problematic is m => m.ReportData1. It's not dynamic so the first loop through is fine but on the second loop through an exception is thrown: System.ArgumentException {"Column 'ReportData1.StringValue' already exist in the grid"}. I know the m.ReportData1 needs to be changed or the approach modified...just don't know how to go about it.
Edit #1: Disabled the foreach per VitezslavSimon's insight. The same exception message is being thrown.
Edit #2: Base class of grid (I think).
public class Grid<T> : GridBase<T>, IGrid where T : class
{
public Grid(IEnumerable<T> items);
public Grid(IQueryable<T> items);
public IGridColumnCollection<T> Columns { get; }
public bool DefaultFilteringEnabled { get; set; }
public bool DefaultSortEnabled { get; set; }
public virtual int DisplayingItemsCount { get; }
public bool EnablePaging { get; set; }
public string Language { get; set; }
public IGridPager Pager { get; set; }
public GridRenderOptions RenderOptions { get; set; }
public ISanitizer Sanitizer { get; set; }
public override IGridSettingsProvider Settings { get; set; }
public virtual void AutoGenerateColumns();
protected internal virtual IEnumerable<T> GetItemsToDisplay();
}
It seems you need to add columns only once there. Try to help it by declaring a flag there. It also depends how your grid component is working behind.
Your code with draft of proposed change:
public ReportGrid(List<ReportRowDataContract> items)
: base(items)
{
// get count of how many fields exist in ReportRowDataContract
int reportDataFieldCount = (new ReportRowDataContract()).GetReportDataFieldCount();
// create columns for grid for each field in ReportRowDataContract
bool flag = true;
foreach (ReportRowDataContract item in items)
{
int i = 0;
if (flag) {
while (i < reportDataFieldCount)
{
AddGridColumn(items[0][i]);
i++;
}
flag = false;
}
}
}
I am building a parser for a custom pipe delimited file format and I am finding my code to be very bulky, could someone suggest better methods of parsing this data?
The file's data is broken down by a line delimited by a pipe (|), each line starts with a record type, followed by an ID, followed by different number of columns after.
Ex:
CDI|11111|OTHERDATA|somemore|other
CEX001|123131|DATA|data
CCC|123131|DATA|data1|data2|data3|data4|data5|data6
. I am splitting by pipe, then grabbing the first two columns, and then using a switch checking the first line and calling a function that will parse the remaining into an object purpose built for that record type. I would really like a more elegant method.
public Dictionary<string, DataRecord> Parse()
{
var data = new Dictionary<string, DataRecord>();
var rawDataDict = new Dictionary<string, List<List<string>>>();
foreach (var line in File.ReadLines(_path))
{
var split = line.Split('|');
var Id = split[1];
if (!rawDataDict.ContainsKey(Id))
{
rawDataDict.Add(Id, new List<List<string>> {split.ToList()});
}
else
{
rawDataDict[Id].Add(split.ToList());
}
}
rawDataDict.ToList().ForEach(pair =>
{
var key = pair.Key.ToString();
var values = pair.Value;
foreach (var value in values)
{
var recordType = value[0];
switch (recordType)
{
case "CDI":
var cdiRecord = ParseCdi(value);
if (!data.ContainsKey(key))
{
data.Add(key, new DataRecord
{
Id = key, CdiRecords = new List<CdiRecord>() { cdiRecord }
});
}
else
{
data[key].CdiRecords.Add(cdiRecord);
}
break;
case "CEX015":
var cexRecord = ParseCex(value);
if (!data.ContainsKey(key))
{
data.Add(key, new DataRecord
{
Id = key,
CexRecords = new List<Cex015Record>() { cexRecord }
});
}
else
{
data[key].CexRecords.Add(cexRecord);
}
break;
case "CPH":
CphRecord cphRecord = ParseCph(value);
if (!data.ContainsKey(key))
{
data.Add(key, new DataRecord
{
Id = key,
CphRecords = new List<CphRecord>() { cphRecord }
});
}
else
{
data[key].CphRecords.Add(cphRecord);
}
break;
}
}
});
return data;
}
Try out FileHelper, here is your exact example - http://www.filehelpers.net/example/QuickStart/ReadFileDelimited/
Given you're data of
CDI|11111|OTHERDATA|Datas
CEX001|123131|DATA
CCC|123131
You could create a class to model this to allow FileHelpers to parse the delimited file:
[DelimitedRecord("|")]
public class Record
{
public string Type { get; set; }
public string[] Fields { get; set; }
}
Then we could allow FileHelpers to parse in to this object type:
var engine = new FileHelperEngine<Record>();
var records = engine.ReadFile("Input.txt");
After we've got all the records loaded in to Record objects we can use a bit of linq to pull them in to their given types
var cdis = records.Where(x => x.Type == "CDI")
.Select(x => new Cdi(x.Fields[0], x.Fields[1], x.Fields[2])
.ToArray();
var cexs = records.Where(x => x.Type == "CEX001")
.Select(x => new Cex(x.Fields[0], x.Fields[1)
.ToArray();
var cccs = records.Where(x => x.Type == "CCC")
.Select(x => new Ccc(x.Fields[0])
.ToArray();
You could also simplify the above using something like AutoMapper - http://automapper.org/
Alternatively you could use ConditionalRecord attributes which will only parse certain lines if they match a given criteria. This will however be slower the more record types you have but you're code will be cleaner and FileHelpers will be doing most of the heavy lifting:
[DelimitedRecord("|")]
[ConditionalRecord(RecordCondition.IncludeIfMatchRegex, "^CDI")]
public class Cdi
{
public string Type { get; set; }
public int Number { get; set; }
public string Data1 { get; set; }
public string Data2 { get; set; }
public string Data3 { get; set; }
}
[DelimitedRecord("|")]
[ConditionalRecord(RecordCondition.IncludeIfMatchRegex, "^CEX001")]
public class Cex001
{
public string Type { get; set; }
public int Number { get; set; }
public string Data1 { get; set; }
}
[DelimitedRecord("|")]
[ConditionalRecord(RecordCondition.IncludeIfMatchRegex, "^CCC")]
public class Ccc
{
public string Type { get; set; }
public int Number { get; set; }
}
var input =
#"CDI|11111|Data1|Data2|Data3
CEX001|123131|Data1
CCC|123131";
var CdiEngine = new FileHelperEngine<Cdi>();
var cdis = CdiEngine.ReadString(input);
var cexEngine = new FileHelperEngine<Cex001>();
var cexs = cexEngine.ReadString(input);
var cccEngine = new FileHelperEngine<Ccc>();
var cccs = cccEngine.ReadString(input);
Your first loop isn't really doing anything other than organizing your data differently. You should be able to eliminate it and use the data as it is from the file. Something like this should give you what you want:
foreach (var line in File.ReadLines(_path))
{
var split = line.Split('|');
var key = split[1];
var value = split;
var recordType = value[0];
switch (recordType)
{
case "CDI":
var cdiRecord = ParseCdi(value.ToList());
if (!data.ContainsKey(key))
{
data.Add(key, new DataRecord
{
Id = key, CdiRecords = new List<CdiRecord>() { cdiRecord }
});
}
else
{
data[key].CdiRecords.Add(cdiRecord);
}
break;
case "CEX015":
var cexRecord = ParseCex(value.ToList());
if (!data.ContainsKey(key))
{
data.Add(key, new DataRecord
{
Id = key,
CexRecords = new List<Cex015Record>() { cexRecord }
});
}
else
{
data[key].CexRecords.Add(cexRecord);
}
break;
case "CPH":
CphRecord cphRecord = ParseCph(value.ToList());
if (!data.ContainsKey(key))
{
data.Add(key, new DataRecord
{
Id = key,
CphRecords = new List<CphRecord>() { cphRecord }
});
}
else
{
data[key].CphRecords.Add(cphRecord);
}
break;
}
};
Caveat: This is just put together here and hasn't been properly checked for syntax.
I have a problem with checking for list equality.
I have the following list:
List<RequestDetailViewModel> requestDetail
that RequestDetailViewModel is :
public int PropertiesValueID { get; set; }
public int UnitID { get; set; }
public string Value { get; set; }
public int PropertyID { get; set; }
and i have another list "reqList":
var reqList = (from p in db.RequestDetail
group new
{ p.PropertyID, p.UnitID , p.Value , p.PropertiesValueID }
by p.RequestID into reqG
select reqG
);
i want to check list equality Like this:
foreach (var item in reqList)
{
if (requestDetail equals item)
{
return true;
}
}
How can I solve this?
Modify your reqList select:
var reqList = (from p in db.RequestDetail
group new
{ p.PropertyID, p.UnitID , p.Value , p.PropertiesValueID }
by p.RequestID into reqG
select new RequestDetailViewModel{
PropertyID = reqG.PropertyID, UnitID = reqG.UnitID ,
Value = reqG.Value ,
PropertiesValueID = reqG.PropertiesValueID
});
Will return List<RequestDetailViewModel>
Implement IComparable for your RequestDetailViewModel class then use SequenceEqual to compare two lists
Why don't you loop your View Model list, linq-querying the domain list for each item. Something like:
foreach (var detail in requestDetail)
{
var reqListEqualItems = (from p in db.RequestDetail
where p.PropertyID == details.PropertyID &&
p.UnitID == details.UnitID &&
p.Value == details.Value &&
p.PropertyID == details.PropertyID);
}
Something like that should give you the Domain Object items for each ViewModel item.
I would update the RequestDetailViewModel as follows:
public class RequestDetailViewModel : INotifyPropertyChanged
{
private ResultDetail resultDetail;
public RequestDetailViewModel(ResultDetail resultDetail)
{
this.resultDetail = resultDetail;
}
public ResultDetail
{
get
{
return this.resultDetail;
}
}
public int PropertiesValueID
{
get
{
return this.resultDetail.PropertiesValueID;
}
set
{
this.resultDetail.PropertiesValueID = value;
this.RaisePropertyChanged("PropertiesValueID");
}
}
public int UnitID
{
get
{
return this.resultDetail.UnitID ;
}
set
{
this.resultDetail.UnitID = value;
this.RaisePropertyChanged("UnitID");
}
}
public string Value
{
get
{
return this.resultDetail.Value;
}
set
{
this.resultDetail.Value= value;
this.RaisePropertyChanged("Value");
}
}
public int PropertyID
{
get
{
return this.resultDetail.PropertyID ;
}
set
{
this.resultDetail.PropertyID = value;
this.RaisePropertyChanged("PropertyID");
}
}
}
I'd also implement IEquatable in your DB model.
and I'd do the check like this:
foreach (var item in reqList)
{
if (requestDetail.ResultDetail.Equals(item))
{
return true;
}
}
or better yet
return reqList.Any(item=> item.Equals(requestDetail.ResultDetail));