I have two problem. I need to serialize data to csv and xml but its turn out to be problematic for me.
As xml I desire to get something like:
<sentence>
<word>example1</word>
<word>example2</word>
<word>example3</word>
</sentence>
<sentence>
<word>example1</word>
<word>example2</word>
<word>example3</word>
</sentence>
My data its SentencedModel which contain inside collection of WordsModel. So it like: List<ICollection<string>>. Every position (sentence) in list have collection of string (words).
Class look like:
[Serializable]
public class WordsModel : IEnumerable<string>
{
[XmlRoot("Word")]
public ICollection<string> Words { get; set;}
public IEnumerator<string> GetEnumerator()
{
return this.Words.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.Words.GetEnumerator();
}
}
[Serializable]
public class SentencedModel : IEnumerable<WordsModel>
{
[XmlArray("Sentence"), XmlArrayItem(typeof(WordsModel), ElementName = "Words")]
public ICollection<WordsModel> Sentences { get; set; }
public SentencedModel()
{
this.Sentences = new List<WordsModel>();
}
public void Add(WordsModel words)
{
this.Sentences?.Add(words);
}
public IEnumerator<WordsModel> GetEnumerator()
{
return this.Sentences.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.Sentences.GetEnumerator();
}
}
My class which is Repositories for that:
public class WordsSeperapedBySentence
{
public SentencedModel WordsSeperatedBySentence { get; }
public WordsSeperapedBySentence()
{
this.WordsSeperatedBySentence = new SentencedModel();
}
public bool AddSentence(ICollection<string> words)
{
if (words == null) return false;
WordsModel wordsModel = new WordsModel();
wordsModel.Words = words;
this.WordsSeperatedBySentence.Add(wordsModel);
return true;
}
}
Here is my serializer class:
public class SerializeData
{
public string SerializeToXml(SentencedModel data)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(SentencedModel));
using (StringWriter textWriter = new StringWriter())
{
xmlSerializer.Serialize(textWriter, data);
return textWriter.ToString();
}
}
public ToCsv(WordsSeperapedBySentence data)
{
//??
}
}
But after using
List<string> example1 = new List<string>();
example1.Add("Chris");
example1.Add("call");
example1.Add("Anna");
List<string> example2 = new List<string>();
example2.Add("Somebody");
example2.Add("call");
example2.Add("Wolf");
WordsModel words1 = new WordsModel();
WordsModel words2 = new WordsModel();
words1.Words = example1;
words2.Words = example2;
SentencedModel sentenced = new SentencedModel();
sentenced.Add(words1);
sentenced.Add(words2);
SerializeData serialize = new SerializeData();
var stringAsResult = serialize.SerializeToXml(sentenced);
Console.WriteLine(stringAsResult);
I got errors. Also I do not have idea how to storage them to CSV.
Could you help me?
Thank you in advance.
In order to save your data as CSV, you can use the following method which provides this output:
Chris,call,Anna
Somebody,call,Wolf
Each line is a sentence then all the words are separated by commas.
public string ToCsv(SentencedModel data)
{
var csvLines = data.Select(x => String.Join(",", x));
var csv = String.Join(Environment.NewLine, csvLines);
return csv;
}
I am still missing the XML part, if I do, I will edit the answer.
At least you have a part of it.
Edit Please find below the ToCsv with the fields being escaped based on the comments below.
public string ToCsv(SentencedModel data)
{
var csvLines = data.Sentences.Select(x => String.Join(",", x.Words.Select(w => EscapeForCsv(w))));
var csv = String.Join(Environment.NewLine, csvLines);
return csv;
}
private string EscapeForCsv(string input)
{
return String.Format("\"{0}\"", input.Replace("\"", "\"\"\""));
}
First: If you want to tokenize a text - I recommend:
use an array and not a list. For example: string[][]. The reason: List will locate 10%-20% more memory. You can convert a List to Array by .ToArray() (e.g. example1.ToArray) or use the C# 6.0 syntax:
string[][] sentence = new [] { {"Chris","called","Anna"}, {"Somebody","called","Wolf"} };
If possible: use the primitive datatypes - classes are to complex and slowdown your textprocessing.
Second: If you want to implement your own serializer try this approce:
public abstract class AbstractSerializer
{
public abstract void Serialize(string[][] model, string path);
}
public class XmlSerializer : AbstractSerializer
{
public override void Serialize(string[][] model, string path)
{
// your stuff
}
}
public class CsvSerializer : AbstractSerializer
{
public string LineSeparator { get; set; } = "\r\n";
public string ValueSeparator { get; set; } = ";";
public override void Serialize(string[][] model, string path)
{
var stb = new System.Text.StringBuilder();
for (int i = 0; i < model.Length; i++)
{
for (int j = 0; j < model[i].Length; j++)
{
// Example output:
// 0;0;Chris
// 0;1;call
// 0;2;Anna
// 1;0;Somebody
// 1;1;call
// 1;2;Wolf
stb.Append(string.Join(ValueSeparator, i, j, model[i][j], LineSeparator));
}
}
}
}
Related
I would like to deserialize CSVs to objects, mapping by varied column names, as illustrated by the following examples:
Input 1
Id;Name;Document
1;Matheus;555777
2;Clarice;567890
Input 2
"Id_Person";"First_Name";"Phone"
3;"John";"999-9999"
public class People
{
public int PersonId { get; set; }
public string Name { get; set; }
public string Doc { get; set; }
}
Note that the column names change by file, and a column can even be missing.
I would like to map "Id" and "Id_Person" to the PersonId property, and so on.
How to do it?
Actually found something that solved my problem: CsvHelper
Setting up:
public sealed class PessoaCSVMap : ClassMap<Pessoas>
{
public PessoaCSVMap()
{
Map(m => m.NomeCompleto).Name("Nome", "Name");
Map(m => m.Documento).Name("Documento", "Doc", "CPF");
Map(m => m.Email1).Name("Email", "Email1", "E-mail", "E-mail1");
Map(m => m.PessoaId).Ignore();
}
}
Using:
const string CSV = "Nome;Email;bleu\nMatheus;matheus.lacerda#email.com.br;blau\nClarice;null;null";
CsvReader csv = new CsvReader(new StringReader(CSV));
csv.Configuration.RegisterClassMap<PessoaCSVMap>();
csv.Configuration.Delimiter = ";";
csv.Configuration.HeaderValidated = null;
csv.Configuration.MissingFieldFound = null;
List<Pessoas> pessoas = csv.GetRecords<Pessoas>().ToList();
Assuming you already can read a specific CSV Line, this one manages to give a lot of flexibility with some reflection and generics . Not a works for all method, but it's easy to adapt it for different cases :
public IEnumerable<T> ProccessCSV<T>(StreamReader document, char divider)
where T : class, new()
{
string currentLine = reader.ReadLine();
string[] usedHeaders = currentLine.Split(divider);
while ((currentLine = reader.ReadLine()) != null)
{
var fields = currentLine.Split(divider);
var result = new T();
for (var i = 0; i < usedHeaders.Length; i++)
{
var value = fields[i];
var propInfo = typeof(T).GetProperties()[i];
result.GetType()
.GetProperty(propInfo.Name)
.SetValue(result, value);
}
yield return result;
}
}
Hope this works as a backbone to a possible solution.
For the first case, you'll need to use a separator ';' and a class like :
public class Person
{
public string Id { get; set; }
public string Name { get; set; }
public string Document { get; set; }
}
Based on : https://www.pluralsight.com/guides/microsoft-net/building-a-generic-csv-writer-reader-using-reflection
I am attempting to iterate through existing sounds (isolatedGroup) and checking if each still exists in the list provided by assetsGroup. If not, I want it removed. I am getting 3 errors when I add the portion of code for iterating.
Errors:
Operator '<' cannot be applied to operands of type 'int' and 'method group'
Cannot apply indexing with [] to an expression of type SaveSoundGroup'
.SaveSoundGroup' does not contain a definition for 'RemoveAt' and no extension method 'RemoveAt' accepting a first argument of type .SaveSoundGroup' could be found (are you missing a using directive or an assembly reference?)
The errors occur at
for (int i = 0; i < isolatedGroup.Count; i++)
{
if (!assetsGroup.Contains(isolatedGroup[i]))
{
isolatedGroup.RemoveAt(i);
i--;
}
Full code:
private SoundGroup LoadFromXml(string xmlName)
{
SaveSoundGroup isolatedGroup = new SaveSoundGroup();
SaveSoundGroup assetsGroup;
XmlSerializer serializer = new XmlSerializer(typeof(SaveSoundGroup));
using (Stream fileStream = Application.GetResourceStream(new Uri("Xmls/" + xmlName, UriKind.Relative)).Stream)
{
assetsGroup = (SaveSoundGroup)serializer.Deserialize(fileStream);
}
if (IsolatedStorageFile.GetUserStoreForApplication().FileExists(xmlName))
{
using (Stream fileStream = IsolatedStorageFile.GetUserStoreForApplication().OpenFile(xmlName, FileMode.Open, FileAccess.Read))
{
isolatedGroup = (SaveSoundGroup)serializer.Deserialize(fileStream);
}
foreach (var entry in assetsGroup.Items)
{
if (!isolatedGroup.Items.Contains(entry))
{
isolatedGroup.Items.Add(entry);
}
}
for (int i = 0; i < isolatedGroup.Count; i++)
{
if (!assetsGroup.Contains(isolatedGroup[i]))
{
isolatedGroup.RemoveAt(i);
i--;
}
}
}
else
{
isolatedGroup = assetsGroup;
}
return new SoundGroup(isolatedGroup);
}
SavedSoundGroup code:
public class SoundGroup
{
public string Title { get; set; }
public List<Group<SoundData>> Items { get; set; }
public SoundGroup()
{
Items = new List<Group<SoundData>>();
}
public SoundGroup(SaveSoundGroup data)
{
this.Title = data.Title;
this.Items = new List<Group<SoundData>>();
foreach (var group in data.Items.GroupBy(item => item.Groups))
{
this.Items.Add(new Group<SoundData>(group.Key, group.ToList()));
}
}
}
public class SaveSoundGroup
{
public string Title { get; set; }
public List<SoundData> Items { get; set; }
public SaveSoundGroup()
{
this.Title = string.Empty;
this.Items = new List<SoundData>();
}
public SaveSoundGroup(SoundGroup data)
: this()
{
if (data != null)
{
this.Title = data.Title;
this.Items = new List<SoundData>();
foreach (var group in data.Items)
{
this.Items.AddRange(group);
}
}
}
}
Sample of XML:
<SaveSoundGroup xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Title>cellular os</Title>
<Items>
<SoundData>
<Title>** Outro Lex Ring **</Title>
<FilePath>https://*********/Outro_Lex_Ring.mp3</FilePath>
<Groups>Animals</Groups>
<SavePath>Outro Lex Ring.mp3</SavePath>
<Status>NotDownloaded</Status>
<DownloadProgress>0</DownloadProgress>
</SoundData>
<SoundData>
<Title>Blackberry 3Beeps</Title>
<FilePath>https://*********/Blackberry_3Beeps.mp3</FilePath>
<Groups>Blackberry</Groups>
<SavePath>Blackberry_3Beeps.mp3</SavePath>
<Status>NotDownloaded</Status>
<DownloadProgress>0</DownloadProgress>
</SoundData>
This sort of sounds like you want to do a union operation. So consider to do isolatedGroup.Union(assetsGroup) to get an Enumerable of all soundGroups that are in both lists.
The error you get is probably due to a missing () after Count but that depends on how it is defined in SaveSoundGroup. Same goes for the other errors. It seems SaveSoundGroup should inherit from ICollection or Collection but is not defined that way. That's why a lot of stuff your are using does not work. So please consider to post the code of your SaveSoundGroup class.
UPDATE
Ok, after having your SaveSoundGroup class I would recommend to do it like this:
public class SoundGroup : List<Group<SoundData>>
{
public string Title { get; set; }
public SoundGroup() {}
public SoundGroup(SaveSoundGroup data) : base(data.GroupBy(item => item.Groups).Select(grp => new Group<SoundData>(grp.Key, grp.ToList())))
{
this.Title = data.Title;
}
}
public class SaveSoundGroup : List<SoundData>
{
public string Title { get; set; }
public SaveSoundGroup()
{
this.Title = string.Empty;
}
public SaveSoundGroup(SoundGroup data)
: base()
{
this.Title = data.Title;
foreach(var grp in data)
this.AddRange(grp);
}
}
Stuff like Count and LINQ should work now. So you can do what you want now with isolatedGroup.Union(assetsGroup) as I already wrote.
Found the solution:
for (int i = 0; i < isolatedGroup.Items.Count; i++)
{
if (!assetsGroup.Items.Contains(isolatedGroup.Items[i]))
{
isolatedGroup.Items.RemoveAt(i);
i--;
}
}
I am trying to create a jumplist for a LongListSelector, I used the AlphaKeyGroup example from MS as a basis.
Once I have created my list I then want to serialize it and store it until the app is next opened.
The problem I have is that the Key is null when I deserialize the ObservableCollection.
I have something like this on my Main Page
public ObservableCollection<AlphaKeyGroup<myClass>> myList { get; set; }
void process()
{
myList = AlphaKeyGroup<myClass>.CreateGroups(System.Threading.Thread.CurrentThread.CurrentUICulture);
getItemsAndAddtoList();
string serializedata = Serialize(myList);
}
void getItemsAndAddtoList()
{
List<myClass> templist=new List<myClass>();
templist.Add(new myClass("Alpha","A in the jumplist"));
templist.Add(new myClass("Beta", "B in the jumplist"));
templist.Add(new myClass("Cappa", "C in the Jumplist"));
addToList(templist.ToArray());
string data = Serialize(myList);
}
void addToList(myClass[] items)
{
if (this.mainList.Dispatcher.CheckAccess())
{
SortedLocaleGrouping slg = new SortedLocaleGrouping(System.Threading.Thread.CurrentThread.CurrentUICulture);
foreach (myClass item in items)
{
int index = 0;
if (slg.SupportsPhonetics)
{
}
else
{
index = slg.GetGroupIndex(item.description);
}
if (index >= 0 && index < myList.Count)
{
myList[index].Add(item);
}
}
}
else
{
this.mainList.Dispatcher.BeginInvoke(new Action<myClass[]>(addToList), new object[] { items });
}
}
public static string Serialize(object obj)
{
using (var sw = new StringWriter())
{
var serializer = new XmlSerializer(obj.GetType());
serializer.Serialize(sw, obj);
return sw.ToString();
}
}
If I break on return sw.ToString(); I can see something like this
<ArrayOfMyClass>
<myClass>
<description>Alpha</description>
<data>A in the jumplist</data>
</myClass>
</ArrayOfMyClass>
As you can see the key from the AlphaKeyGroup class is missing, if I then deserialise this back and set it as the LongListSelector ItemSource I get a Jumplist with No text values, just empty boxes.
public class myClass
{
public string description { get; set; }
public string data { get; set; }
public myClass()
{
}
public myClass(string Desc, string Data)
{
description = Desc;
data = Data;
}
}
public class AlphaKeyGroup<T> : ObservableCollection<T>
{
public delegate string GetKeyDelegate(T item);
public string Key { get; set; }
public AlphaKeyGroup(string key)
{
Key = key;
}
public AlphaKeyGroup()
{
}
public static ObservableCollection<AlphaKeyGroup<T>> CreateGroups(CultureInfo ci)
{
SortedLocaleGrouping slg = new SortedLocaleGrouping(ci);
ObservableCollection<AlphaKeyGroup<T>> list = new ObservableCollection<AlphaKeyGroup<T>>();
foreach (string key in slg.GroupDisplayNames)
{
list.Add(new AlphaKeyGroup<T>(key));
}
return list;
}
}
I am sure I am missing something simple, but I couldn't find a solution, I think it is to do with the Parameterless constructor, but I am not sure, I am quite new to C#.
Looking for a good way to parse out of this text file, the values highlighted with the yellow boxes using C#. Each section is delineated by a TERM # which I forgot to highlight. Tried this:
string fileName = "ATMTerminalTotals.txt";
StreamReader sr = new StreamReader(fileName);
string[] delimiter = new string[] { " " };
while (!sr.EndOfStream)
{
string[] lines = sr.ReadLine().Split(delimiter, StringSplitOptions.RemoveEmptyEntries);
foreach (string line in lines)
{
Console.WriteLine(line);
}
}
Console.ReadLine();
Safe to say I am reading lines correctly and removing "white spaces." Although, as an amateur to programming, not sure of a valid way to accurately "know" that I am getting the values from this report that I need. Any advice?
i've tested this with a very simple program to parse the given file,
basically i've created two basic classes, a page class holding a collection of terminal report class (the tran type rows)
these rows maybe even can be represented as transaction and a billing class too
first parsed the data, setting the parameters needed and lastly just accessing the properties
just rushed it to be as simple as possible, no error handling etc... its just to give you a sense of how id start solving these kind of tasks, hope it helps
Adam
namespace TerminalTest
{
class Program
{
public class TerminalReport
{
public string Word { get; set; }
public int Denials { get; set; }
public int Approvals { get; set; }
public int Reversals { get; set; }
public double Amount { get; set; }
public int ON_US { get; set; }
public int Alphalink { get; set; }
public int Interchange { get; set; }
public int Surcharged { get; set; }
public static TerminalReport FromLine(string line)
{
TerminalReport report = new TerminalReport();
report.Word = line.Substring(0, 11);
line = line.Replace(report.Word, string.Empty).Trim();
string[] split = line.Split(' ');
int i = 0;
// transaction summary
report.Denials = int.Parse(split[i++]);
report.Approvals = int.Parse(split[i++]);
report.Reversals = int.Parse(split[i++]);
report.Amount = double.Parse(split[i++]);
// billing counts
report.ON_US = int.Parse(split[i++]);
report.Alphalink = int.Parse(split[i++]);
report.Interchange = int.Parse(split[i++]);
report.Surcharged = int.Parse(split[i++]);
return report;
}
}
public class TerminalPage
{
public int PageNumber { get; set; }
public double TotalSurcharges { get; set; }
public List<TerminalReport> Rows { get; set; }
public TerminalPage(int num)
{
PageNumber = num;
Rows = new List<TerminalReport>();
}
public int TotalDenials
{
get
{
return rows.Sum(r => r.Denials);
}
}
public int TotalApprovals
{
get
{
return Rows.Sum(r => r.Approvals;
}
}
public int TotalReversals
{
get
{
return Rows.Sum(r => r.Reversals;
}
}
public double TotalAmount
{
get
{
return Rows.Sum(r => r.Amount);
}
}
public int TotalON_US
{
get
{
return Rows.Sum(r => r.ON_US);
}
}
public int TotalAlphalink
{
get
{
return Rows.Sum(r => r.Alphalink);
}
}
public int TotalInterchange
{
get
{
return Rows.Sum(r => r.Interchange);
}
}
public int TotalSurcharged
{
get
{
return Rows.Sum(r => r.Surcharged);
}
}
}
private static string CleanString(string text)
{
return Regex.Replace(text, #"\s+", " ").Replace(",", string.Empty).Trim();
}
private static List<TerminalPage> ParseData(string filename)
{
using (StreamReader sr = new StreamReader(File.OpenRead(filename)))
{
List<TerminalPage> pages = new List<TerminalPage>();
int pageNumber = 1;
TerminalPage page = null;
bool parse = false;
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
line = CleanString(line);
if (line.StartsWith("TRAN TYPE"))
{
// get rid of the ----- line
sr.ReadLine();
parse = true;
if (page != null)
{
pages.Add(page);
}
page = new TerminalPage(pageNumber++);
}
else if (line.StartsWith("="))
{
parse = false;
}
else if (line.StartsWith("TOTAL SURCHARGES:"))
{
line = line.Replace("TOTAL SURCHARGES:", string.Empty).Trim();
page.TotalSurcharges = double.Parse(line);
}
else if (parse)
{
TerminalReport r = TerminalReport.FromLine(line);
page.Rows.Add(r);
}
}
if (page != null)
{
pages.Add(page);
}
return pages;
}
}
static void Main(string[] args)
{
string filename = #"C:\bftransactionsp.txt";
List<TerminalPage> pages = ParseData(filename);
foreach (TerminalPage page in pages)
{
Console.WriteLine("TotalSurcharges: {0}", page.TotalSurcharges);
foreach (TerminalReport r in page.Rows)
Console.WriteLine(r.Approvals);
}
}
}
}
I'm not sure I'd split it by spaces actually.. the textfile looks like its split into columns. You might want to read like 10 chars (or whatever the width of the column is) at a time... and I'd parse the whole file into a dictionary so you get entries like
dict["WDL FRM CHK"]["# DENIALS"] = 236
then you can easily retrieve the values you want from there, and if you ever need more values in the future, you've got them.
Alternatively, you can use regexs. You can grab the first value with a regex like
^WDL FRM CHK\s+(?<denials>[0-9,]+)\s+(?<approvals>[0-9,]+)$
using
m.Groups["approvals"]
anyway I recommend you to wrap your StreamReader with using block:
using (StreamReader sr = new StreamReader(fileName))
{
// do stuff
}
Read more on MSDN
Given that it seems to have a standard, regular format, I would use regular expressions. You can check the starting code to figure out what row you're on, then an expression that will parse out the numbers and ignore whitespace will, very likely, be easier than handling it manually.
using System;
using System.Text.RegularExpressions;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
Regex exp = new Regex(#"WDL FRM CHK(\s)+[1-9,]+(\s)+(?<approvals>[1-9,]+)(\s)+");
string str = "WDL FRM CHK 236 1,854 45,465 123 3";
Match match = exp.Match(str);
if (match.Success)
{
Console.WriteLine("Approvals: " + match.Groups["approvals"].Value);
}
Console.ReadLine();
}
}
}
Apdated from the following article to parse one of your numbers:
How to match a pattern by using regular expressions and Visual C#
I just cannot get this to work, would appreciate if someone can help.
So I get back an XML result from a database which looks like:
<matches>
<issuer client_name="MTR" score="6" match_list="MTR CORPORATION LIMITED"/>
<issuer client_name="PEOPLE''S REPUBLIC OF CHINA" score="4"
match_list="DEMOCRATIC PEOPLE'S REPUBLIC OF KOREA;GOVERNMENT OF THE
HONG KONG SPECIAL ADMINISTRATIVE REGION OF THE PEOPLE'S REPUBLIC OF
CHINA;MONGOLIAN PEOPLE'S REPUBLIC;PEOPLE'S DEMOCRATIC REPUBLIC OF
ALGERIA;PEOPLE'S REPUBLIC OF CHINA"/>
</matches>
From this XML I need to populate an object after doing some logic like matching the client_name I am getting back in the XML result to the one I have sent to database to get matches.
XDocument.Load(new StringReader(
row.GetString(row.GetOrdinal("xml_ret"))))))
.Single().Descendants("matches")
.Select(x =>
new Pool() {
Constituents = (IEnumerable<Constituent>)
//(... cannot work this how can IsReference populate)
//ClientName = x.Attribute("client_name").Value,
//Score = x.Attribute("score").Value,
//MatchList = x.Attribute("match_list").Value,
});
In a non-LINQ manner I can populate the object something like this:
foreach (Constituent constituent in pool.Constituents)
{
if (!string.IsNullOrEmpty(constituent.Name)
&& string.IsNullOrEmpty(constituent.Curve))
{
i++;
ConstituentMatch match = new ConstituentMatch();
ConstituentMatch.Group group =new ConstituentMatch.Group("High");
//High Match group
ICollection<string> curves = new List<string>();
curves.Add("EUR" + i);
curves.Add("USD" + i);
ICollection<string> names = new List<string>();
ConstituentMatch.Group.Entry entry =
new ConstituentMatch.Group.Entry(constituent.Name + " Ltd.",
curves);
group.Add(entry);
entry =
new ConstituentMatch.Group.Entry(constituent.Name + " Inc.",
curves);
group.Add(entry);
match.AddGroup(group);
}
}
But how can I do this using LINQ, as I am sure you can do it, I just cannot work it out.
The constituent class looks like:
public sealed class Constituent
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
public ConstituentMatch Match {get;set;}
public Constituent(string name)
{
this.name = name;
}
public Constituent() : this(string.Empty) { }
}
And constituent match class looks like this:
public sealed class ConstituentMatch
{
private readonly Dictionary<string, Group> matches = new Dictionary<string, Group>();
public IEnumerable<string> GroupNames
{
get { return matches.Keys; }
}
public Group this[string name]
{
get { return matches[name]; }
}
public IEnumerable<Group> Groups
{
get { return matches.Values; }
}
public void AddGroup(Group group)
{
matches[group.Name] = group;
}
/// <summary>
/// Match group e.g. Poor, High, All, Begins With
/// </summary>
public sealed class Group
{
private readonly string name;
private readonly ICollection<Entry> matches = new List<Entry>();
public string Name
{
get { return name; }
}
public Group(string name)
{
this.name = name;
}
public void Add(Entry entry)
{
matches.Add(entry);
}
public override bool Equals(object obj)
{
bool result = false;
if (obj is Group)
{
Group other = obj as Group;
result = name == other.name;
}
return result;
}
public override int GetHashCode()
{
return name.GetHashCode();
}
public sealed class Entry
{
private string legalName;
private IEnumerable<string> curves;
private double notional = double.NaN;
private char seniriority = 'N';
public string LegalName
{
get { return legalName; }
}
public IEnumerable<string> Curves
{
get { return curves; }
}
public Entry(string legalName, IEnumerable<string> curves)
: this(legalName, curves, double.NaN, 'N') { }
public Entry(string legalName,
IEnumerable<string> curves,
double notional,
char seniriority)
{
this.legalName = legalName;
this.curves = curves;
this.notional = notional;
this.seniriority = seniriority;
}
}
}
}
Some thing similar to this should work
var haystack = new Pool().Constituents;
var indexedhaystack = haystack.Select((item, index)=> new {
item, index
});
var pool = new Pool()
{
Constituents = from l in indexedhaystack
select new Constituent()
{
//your stuff here
}
};
... extended ...
var constituents = new Pool().Constituents.Select((c, i) =>
new
{
Constituent = c,
Index = i
});
var items = from c in constituents
where !string.IsNullOrEmpty(c.Constituent.Name)
&& string.IsNullOrEmpty(c.Constituent.Curve)
let curves = new[]{
"EUR" + c.Index.ToString(),
"USD" + c.Index.ToString()
}
let match = new ConstituentMatch(){
new Group("High") {
new Entry(
c.Constituent.Name + " Ltd.",
curves),
new Entry(
c.Constituent.Name + " Inc.",
curves)
}
}
select new
{
Name = c.Constituent.Name,
Curves = curves,
Match = match
};
...
public class Constituent
{
public string Name { get; set; }
public string Curve { get; set; }
}
public class Pool
{
public List<Constituent> Constituents { get; set; }
}
public class Entry
{
public Entry(string entry, IEnumerable<string> curves)
{
}
}
public class Group : List<Entry>
{
public Group(string group) { }
}
public class ConstituentMatch : List<Group>
{
}
Language INtegrated Query is, as its name says, a technology for querying objects and data, not for modifying them.