Get the positions of unique elements in a string[] - c#

I have an xml file that I am accessing to create a report of time spent on a project. I'm returning the unique dates to a label created dynamically on a winform and would like to compile the time spent on a project for each unique date. I have been able to return all of the projects under each date or only one project. Currently I'm stuck on only returning one project. Can anyone please help me?? This is what the data should look like if it's correct.
04/11/15
26820 2.25
27111 8.00
04/12/15
26820 8.00
04/13/15
01det 4.33
26820 1.33
27225 4.25
etc.
This is how I'm retrieving the data
string[] weekDateString = elementDateWeekstring();
string[] uniqueDates = null;
string[] weeklyJobNumber = elementJobNumWeek();
string[] weeklyTicks = elementTicksWeek();
This is how I'm getting the unique dates.
IEnumerable<string> distinctWeekDateIE = weekDateString.Distinct();
foreach (string d in distinctWeekDateIE)
{
uniqueDates = distinctWeekDateIE.ToArray();
}
And this is how I'm creating the labels.
try
{
int dateCount;
dateCount = uniqueDates.Length;
Label[] lblDate = new Label[dateCount];
int htDate = 1;
int padDate = 10;
for (int i = 0; i < dateCount; i++ )
{
lblDate[i] = new Label();
lblDate[i].Name = uniqueDates[i].Trim('\r');
lblDate[i].Text = uniqueDates[i];
lblDate[i].TabIndex = i;
lblDate[i].Bounds = new Rectangle(18, 275 + padDate + htDate, 75, 22);
targetForm.Controls.Add(lblDate[i]);
htDate += 22;
foreach (string x in uniqueDates)
{
int[] posJobNumber;
posJobNumber = weekDateString.Select((b, a) => b == uniqueDates[i].ToString() ? a : -1).Where(a => a != -1).ToArray();
for (int pjn = 0; pjn < posJobNumber.Length; pjn++)
{
if (x.Equals(lblDate[i].Text))
{
Label lblJobNum = new Label();
int htJobNum = 1;
int padJobNum = 10;
lblJobNum.Name = weeklyJobNumber[i];
lblJobNum.Text = weeklyJobNumber[i];
lblJobNum.Bounds = new Rectangle(100, 295 + padJobNum + htJobNum, 75, 22);
targetForm.Controls.Add(lblJobNum);
htJobNum += 22;
htDate += 22;
padJobNum += 22;
}
}
}
}
}
I've been stuck on this for about 3 months. Is there anyone that can describe to me why I'm not able to properly retrieve the job numbers that are associated with a particular date. I don't believe that these are specifically being returned as dates. Just a string that looks like a date.
I really appreciate any help I can get. I'm just completely baffled. Thank you for any responses in advance. I truly appreciate the assistance.
EDIT: #Sayka - Here is the xml sample.
<?xml version="1.0" encoding="utf-8"?>
<Form1>
<Name Key="4/21/2014 6:51:17 AM">
<Date>4/21/2014</Date>
<JobNum>26820</JobNum>
<RevNum>00000</RevNum>
<Task>Modeling Secondary</Task>
<Start>06:51 AM</Start>
<End>04:27 PM</End>
<TotalTime>345945089017</TotalTime>
</Name>
<Name Key="4/22/2014 5:44:22 AM">
<Date>4/22/2014</Date>
<JobNum>26820</JobNum>
<RevNum>00000</RevNum>
<Task>Modeling Secondary</Task>
<Start>05:44 AM</Start>
<End>06:56 AM</End>
<TotalTime>43514201221</TotalTime>
</Name>
<Name Key="4/22/2014 6:57:02 AM">
<Date>4/22/2014</Date>
<JobNum>02e-n-g</JobNum>
<RevNum>00000</RevNum>
<Task>NET Eng</Task>
<Start>06:57 AM</Start>
<End>07:16 AM</End>
<TotalTime>11706118875</TotalTime>
</Name>
....
</Form1>
This is how I'm getting the information out of the xml file and returning a string[].
public static string[] elementDateWeekstring()
{
//string datetxtWeek = "";
XmlDocument xmldoc = new XmlDocument();
fileExistsWeek(xmldoc);
XmlNodeList nodeDate = xmldoc.GetElementsByTagName("Date");
int countTicks = 0;
string[] dateTxtWeek = new string[nodeDate.Count];
for (int i = 0; i < nodeDate.Count; i++)
{
dateTxtWeek[i] = nodeDate[i].InnerText;
countTicks++;
}
return dateTxtWeek;
}
Job number and Ticks are returned in a similar fashion. I've been able to reuse these snippets throught out the code. This is a one dimensional xml file?? It will always return a position for a jobnumber that equates to a date or Ticks. I will never have more or less of any one element.

You can use Linq-to-XML to parse the XML file, and then use Linq-to-objects to group (and order) the data by job date and order each group by job name.
The code to parse the XML file is like so:
var doc = XDocument.Load(filename);
var jobs = doc.Descendants("Name");
// Extract the date, job number, and total time from each "Name" element.:
var data = jobs.Select(job => new
{
Date = (DateTime)job.Element("Date"),
Number = (string)job.Element("JobNum"),
Duration = TimeSpan.FromTicks((long)job.Element("TotalTime"))
});
The code to group and order the jobs by date and order the groups by job name is:
var result =
data.GroupBy(job => job.Date).OrderBy(g => g.Key)
.Select(g => new
{
Date = g.Key,
Jobs = g.OrderBy(item => item.Number)
});
Then you can access the data by iterating over each group in result and then iterate over each job in the group, like so:
foreach (var jobsOnDate in result)
{
Console.WriteLine("{0:d}", jobsOnDate.Date);
foreach (var job in jobsOnDate.Jobs)
Console.WriteLine(" {0} {1:hh\\:mm}", job.Number, job.Duration);
}
Putting this all together in a sample compilable console application (substitute the filename for the XML file as appropriate):
using System;
using System.Linq;
using System.Xml.Linq;
namespace ConsoleApplication2
{
class Program
{
private static void Main()
{
string filename = #"d:\test\test.xml"; // Substitute your own filename here.
// Open XML file and get a collection of each "Name" element.
var doc = XDocument.Load(filename);
var jobs = doc.Descendants("Name");
// Extract the date, job number, and total time from each "Name" element.:
var data = jobs.Select(job => new
{
Date = (DateTime)job.Element("Date"),
Number = (string)job.Element("JobNum"),
Duration = TimeSpan.FromTicks((long)job.Element("TotalTime"))
});
// Group the jobs by date, and order the groups by job name:
var result =
data.GroupBy(job => job.Date).OrderBy(g => g.Key)
.Select(g => new
{
Date = g.Key,
Jobs = g.OrderBy(item => item.Number)
});
// Print out the results:
foreach (var jobsOnDate in result)
{
Console.WriteLine("{0:d}", jobsOnDate.Date);
foreach (var job in jobsOnDate.Jobs)
Console.WriteLine(" {0} {1:hh\\:mm}", job.Number, job.Duration);
}
}
}
}

The output is like this
Create a new project
Set form size bigger.
Apply these codes.
Set the location for your XML file.
Namespaces
using System.Xml;
using System.IO;
Form Code
public partial class Form1 : Form
{
const string XML_FILE_NAME = "D:\\emps.txt";
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
prepareDataGrid();
List<JOBS> jobsList = prepareXML(XML_FILE_NAME);
for (int i = 0; i < jobsList.Count; i++)
{
addDateRow(jobsList[i].jobDate.ToString("M'/'d'/'yyyy"));
for (int j = 0; j < jobsList[i].jobDetailsList.Count; j++)
dgv.Rows.Add(new string[] {
jobsList[i].jobDetailsList[j].JobNumber,
jobsList[i].jobDetailsList[j].JobHours
});
}
}
DataGridView dgv;
void prepareDataGrid()
{
dgv = new DataGridView();
dgv.BackgroundColor = Color.White;
dgv.GridColor = Color.White;
dgv.DefaultCellStyle.SelectionBackColor = Color.White;
dgv.DefaultCellStyle.SelectionForeColor = Color.Black;
dgv.DefaultCellStyle.ForeColor = Color.Black;
dgv.DefaultCellStyle.BackColor = Color.White;
dgv.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
dgv.Width = 600;
dgv.Dock = DockStyle.Left;
this.BackColor = Color.White;
dgv.Columns.Add("Col1", "Col1");
dgv.Columns.Add("Col2", "Col2");
dgv.Columns[0].Width = 110;
dgv.Columns[1].Width = 40;
dgv.DefaultCellStyle.Font = new System.Drawing.Font("Segoe UI", 10);
dgv.RowHeadersVisible = dgv.ColumnHeadersVisible = false;
dgv.AllowUserToAddRows =
dgv.AllowUserToDeleteRows =
dgv.AllowUserToOrderColumns =
dgv.AllowUserToResizeColumns =
dgv.AllowUserToResizeRows =
!(dgv.ReadOnly = true);
Controls.Add(dgv);
}
void addJobRow(string jobNum, string jobHours)
{
dgv.Rows.Add(new string[] {jobNum, jobHours });
}
void addDateRow(string date)
{
dgv.Rows.Add(new string[] { date, ""});
dgv.Rows[dgv.Rows.Count - 1].DefaultCellStyle.SelectionForeColor =
dgv.Rows[dgv.Rows.Count - 1].DefaultCellStyle.ForeColor = Color.Firebrick;
dgv.Rows[dgv.Rows.Count - 1].DefaultCellStyle.Font = new Font("Segoe UI Light", 13.5F);
dgv.Rows[dgv.Rows.Count - 1].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
dgv.Rows[dgv.Rows.Count - 1].Height = 25;
}
List<JOBS> prepareXML(string fileName)
{
string xmlContent = "";
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
using (StreamReader sr = new StreamReader(fs)) xmlContent = sr.ReadToEnd();
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlContent);
List<JOBS> jobsList = new List<JOBS>();
XmlNode form1Node = doc.ChildNodes[1];
for (int i = 0; i < form1Node.ChildNodes.Count; i++)
{
XmlNode dateNode = form1Node.ChildNodes[i].ChildNodes[0].ChildNodes[0],
jobNumNode = form1Node.ChildNodes[i].ChildNodes[1].ChildNodes[0],
timeTicksNode = form1Node.ChildNodes[i].ChildNodes[6].ChildNodes[0];
bool foundDate = false;
for (int j = 0; j < jobsList.Count; j++) if (jobsList[j].compareDate(dateNode.Value))
{
jobsList[j].addJob(jobNumNode.Value, Math.Round(TimeSpan.FromTicks(
(long)Convert.ToDouble(timeTicksNode.Value)).TotalHours, 2).ToString());
foundDate = true;
break;
}
if (!foundDate)
{
JOBS job = new JOBS(dateNode.Value);
string jbnum = jobNumNode.Value;
string tbtck = timeTicksNode.Value;
long tktk = Convert.ToInt64(tbtck);
double tkdb = TimeSpan.FromTicks(tktk).TotalHours;
job.addJob(jobNumNode.Value, Math.Round(TimeSpan.FromTicks(
Convert.ToInt64(timeTicksNode.Value)).TotalHours, 2).ToString());
jobsList.Add(job);
}
}
jobsList.OrderByDescending(x => x.jobDate);
return jobsList;
}
class JOBS
{
public DateTime jobDate;
public List<JobDetails> jobDetailsList = new List<JobDetails>();
public void addJob(string jobNumber, string jobHours)
{
jobDetailsList.Add(new JobDetails() { JobHours = jobHours, JobNumber = jobNumber });
}
public JOBS(string dateString)
{
jobDate = getDateFromString(dateString);
}
public JOBS() { }
public bool compareDate(string dateString)
{
return getDateFromString(dateString) == jobDate;
}
private DateTime getDateFromString(string dateString)
{
string[] vals = dateString.Split('/');
return new DateTime(Convert.ToInt32(vals[2]), Convert.ToInt32(vals[0]), Convert.ToInt32(vals[1]));
}
}
class JobDetails
{
public string JobNumber { get; set; }
public string JobHours { get; set; }
}
}

Related

How to write a method in C# to write in a textbox according to the size of data (quantity of registries in database)

I have a working code that has to many lines of repeated code. I would like to write a method to save lines of code.
I have a query that gets the number of registries in the database. The number of registries may vary from 1 to 20. The number of registries is saved in the decimal numberOfLines.
Today I am using 20 if's, that writes 4 textboxes per line for each possible number of lines I have.
If I have only one line it write 1 line of 4 textboxes, if I have 2 lines it writes 2 lines of 4 textboxes and so one.
I will only show the code for the quantity of lines from 1 to 4 just to save space (the rest of the code is just copy/paste and change the textboxes new indexes).
//write the lines according to the number of lines
if (numberOfLines == 1)
{
txt_A1.Text = tableAs.Rows[0][0].ToString();
txt_B1.Text = tableAs.Rows[0][1].ToString();
txt_C1.Text = tableAs.Rows[0][2].ToString();
txt_D1.Text = tableAs.Rows[0][3].ToString();
}
if (numberOfLines ==2)
{
txt_A1.Text = tableAs.Rows[0][0].ToString();
txt_B1.Text = tableAs.Rows[0][1].ToString();
txt_C1.Text = tableAs.Rows[0][2].ToString();
txt_D1.Text = tableAs.Rows[0][3].ToString();
txt_A2.Text = tableAs.Rows[1][0].ToString();
txt_B2.Text = tableAs.Rows[1][1].ToString();
txt_C2.Text = tableAs.Rows[1][2].ToString();
txt_D2.Text = tableAs.Rows[1][3].ToString();
}
if (numberOfLines == 3)
{
txt_A1.Text = tableAs.Rows[0][0].ToString();
txt_B1.Text = tableAs.Rows[0][1].ToString();
txt_C1.Text = tableAs.Rows[0][2].ToString();
txt_D1.Text = tableAs.Rows[0][3].ToString();
txt_A2.Text = tableAs.Rows[1][0].ToString();
txt_B2.Text = tableAs.Rows[1][1].ToString();
txt_C2.Text = tableAs.Rows[1][2].ToString();
txt_D2.Text = tableAs.Rows[1][3].ToString();
txt_A3.Text = tableAs.Rows[2][0].ToString();
txt_B3.Text = tableAs.Rows[2][1].ToString();
txt_C3.Text = tableAs.Rows[2][2].ToString();
txt_D3.Text = tableAs.Rows[2][3].ToString();
}
if (numberOfLines == 4)
{
txt_A1.Text = tableAs.Rows[0][0].ToString();
txt_B1.Text = tableAs.Rows[0][1].ToString();
txt_C1.Text = tableAs.Rows[0][2].ToString();
txt_D1.Text = tableAs.Rows[0][3].ToString();
txt_A2.Text = tableAs.Rows[1][0].ToString();
txt_B2.Text = tableAs.Rows[1][1].ToString();
txt_C2.Text = tableAs.Rows[1][2].ToString();
txt_D2.Text = tableAs.Rows[1][3].ToString();
txt_A3.Text = tableAs.Rows[2][0].ToString();
txt_B3.Text = tableAs.Rows[2][1].ToString();
txt_C3.Text = tableAs.Rows[2][2].ToString();
txt_D3.Text = tableAs.Rows[2][3].ToString();
txt_A4.Text = tableAs.Rows[3][0].ToString();
txt_B4.Text = tableAs.Rows[3][1].ToString();
txt_C4.Text = tableAs.Rows[3][2].ToString();
txt_D4.Text = tableAs.Rows[3][3].ToString();
}
With the amount of possible lines I have (20) the code gets very big, and not as beautiful as I expected (with the use of a method for example).
I write a method that you could create textboxes according to the line.
Code:
private void button1_Click(object sender, EventArgs e)
{
int a = Convert.ToInt32(richTextBox1.Text);
CreateTextbox(a);
}
public void CreateTextbox(int line)
{
int count = 0;
int num = 0;
for (int i = 0; i < line*4; i++)
{
TextBox box = new TextBox();
box.Name = "A" + i.ToString();
if (count >= 4)
{
count = 0;
num++;
}
box.Location = new Point(count*(box.Width+20),num*40);
count++;
this.Controls.Add(box);
}
}
}
Try this refactoring:
var items = new Dictionary<int, List<TextBox>>()
{
{ 1, new List<TextBox>() { txt_A1, txt_B1, txt_C1, txt_D1 } },
{ 2, new List<TextBox>() { txt_A1, txt_B1, txt_C1, txt_D1, txt_A2, txt_B2, txt_C2, txt_D2 } },
{ 3, new List<TextBox>() { txt_A1, txt_B1, txt_C1, txt_D1, txt_A2, txt_B2, txt_C2, txt_D2, txt_A3, txt_B3, txt_C3, txt_D3 } },
{ 4, new List<TextBox>() { txt_A1, txt_B1, txt_C1, txt_D1, txt_A2, txt_B2, txt_C2, txt_D2, txt_A3, txt_B3, txt_C3, txt_D3, txt_A4, txt_B4, txt_C4, txt_D4 } }
};
int index1 = 0;
int index2 = 0;
foreach ( var item in items[numberOfLines] )
{
item.Text = tableAs.Rows[index1][index2].ToString();
if ( ++index2 > 3 )
{
index2 = 0;
index1++;
}
}

Shuffling list of competitors, each month different competitor

for my friends sportscompetition, each player has to play 1 game a month against an other player. Now if i have a list of 20 players or so its not that hard to randomize the first month so i have 10 matches.
All the months after that though i'm not sure how to get the randomizer working so they won't be matched against a player they have played against.
Right now i made an sql database with Players(Name, (int)Id, Email) , Matches(Id, Player1ID, Player2ID)
I'm thinking for a randomize of the list and checking if each match doesn't contain 2 id's from a match in the database. And if 1 match does, redo the entire randomize of that month.
But i'm not sure if thats the best way.
This is what i have so far, i have yet to test it after i add some 'leden' and 'matches' to my database.
private void MaakMatchen(Maand maand)
{
List<Lid> leden = new List<Lid>();
var dbManager = new Manager();
using (var conGildenhof = dbManager.GetConnection())
{
using (var comLeden = conGildenhof.CreateCommand())
{
comLeden.CommandType = CommandType.Text;
comLeden.CommandText = "select * from dbo.Leden";
conGildenhof.Open();
using (var alleleden = comLeden.ExecuteReader())
{
Int32 voornaamPos = alleleden.GetOrdinal("Voornaam");
Int32 familienaamPos = alleleden.GetOrdinal("Familienaam");
Int32 LidNummerPos = alleleden.GetOrdinal("LidNummer");
while (alleleden.Read())
{
leden.Add(new Classes.Lid(alleleden.GetString(voornaamPos), alleleden.GetString(familienaamPos), alleleden.GetInt32(LidNummerPos)));
}
leden = Randomize(leden);
}
}
using (var comInsert = conGildenhof.CreateCommand())
{
comInsert.CommandType = CommandType.Text;
comInsert.CommandText = "Insert into dbo.Matches (Lid1Id, Lid2Id, Maand) values (#lid1, #lid2, #maand)";
var parLid1 = comInsert.CreateParameter();
parLid1.ParameterName = "#lid1";
comInsert.Parameters.Add(parLid1);
var parLid2 = comInsert.CreateParameter();
parLid2.ParameterName = "#lid2";
comInsert.Parameters.Add(parLid2);
var parMaand = comInsert.CreateParameter();
parMaand.ParameterName = "#maand";
comInsert.Parameters.Add(parMaand);
int lengte = leden.Count();
for (int i = 0; i < lengte; i = i + 2)
{
parLid1.Value = leden[i].LidNummer;
parLid2.Value = leden[i + 1].LidNummer;
parMaand.Value = (int)maand;
comInsert.ExecuteNonQuery();
}
}
}
}
private List<Lid> Randomize(List<Lid> leden)
{
for (int i=0;i<100;i++)
{
leden = Shuffle(leden);
}
int temp = CheckUp(leden);
while (temp != 100)
{
leden = Shuffle(leden, temp);
temp = CheckUp(leden);
}
return leden;
}
private List<Lid> Shuffle(List<Lid> leden)
{
Random rnd = new Random();
int a = rnd.Next(1, leden.Count() + 1);
int b = rnd.Next(1, leden.Count() + 1);
var temp = new Lid();
temp = leden[a];
leden[a] = leden[b];
leden[b] = temp;
return leden;
}
private List<Lid> Shuffle(List<Lid> leden, int id)
{
Random rnd = new Random();
int a = rnd.Next(1, leden.Count() + 1);
int b = id;
var temp = new Lid();
temp = leden[a];
leden[a] = leden[b];
leden[b] = temp;
return leden;
}
private int CheckUp(List<Lid> leden)
{
int lengte = leden.Count();
List<Matches> matches = new List<Matches>();
var dbManager = new Manager();
using (var conGildenhof = dbManager.GetConnection())
{
using (var comMatches = conGildenhof.CreateCommand())
{
comMatches.CommandType = CommandType.Text;
comMatches.CommandText = "select * from dbo.Matches";
conGildenhof.Open();
using (var allematches = comMatches.ExecuteReader())
{
Int32 lid1Pos = allematches.GetOrdinal("Lid1Id");
Int32 lid2Pos = allematches.GetOrdinal("Lid2Id");
Int32 maandPos = allematches.GetOrdinal("Maand");
while (allematches.Read())
{
matches.Add(new Classes.Matches(allematches.GetInt32(lid1Pos), allematches.GetInt32(lid2Pos), (Maand)allematches.GetInt32(maandPos)));
}
}
}
}
for (int i=0;i<lengte;i=i+2)
{
foreach (Matches match in matches)
{
if (leden[i].LidNummer == match.Lid1Id)
{
if (leden[i + 1].LidNummer == match.Lid2Id)
return leden[i].LidNummer;
}
if (leden[i].LidNummer == match.Lid2Id)
{
if (leden[i + 1].LidNummer == match.Lid1Id)
return leden[i].LidNummer;
}
}
}
return 100;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var maand = new int();
int.TryParse(TextBoxMaand.Text, out maand);
if (maand == 0)
TextBoxMaand.Text = "GETAL!";
else
{
MaakMatchen((Maand)maand);
}
}
I would shuffle the players first and create the matches in a second iteration
List<Player> players = GetPlayers();
Random _rnd = new Random();
// shuffle players
players = players.OrderBy(_ => _rnd.Next()).ToList();
// create matches
var matches = players.Take(players.Count / 2).Zip(players.Skip(players.Count / 2), (p1, p2) => new Match(p1,p2));
https://dotnetfiddle.net/sGxbx4

"Object reference not set to an instance of an object" error during the compilation

I get the "Object reference not set to an instance of an object" error when i compile the code at string[] values = lineuser.Split(' '); . Any idea?
namespace function
{
public partial class Form1 : Form
{
float userscore,itemscore,result;
string lineitem, lineuser;
//float[][] a = new float[89395][100];
//float[][] b = new float[1143600][100];
float[][] a = Enumerable.Range(0, 89395).Select(i => new float[100]).ToArray();
float[][] b = Enumerable.Range(0, 1143600).Select(j => new float[100]).ToArray();
//float[,] c = new float[89395, 100];
StreamReader fileitem = new StreamReader("c:\\ITEM_SVD_FULL.txt");
StreamReader fileuser = new StreamReader("c:\\USER_SVD_FULL.txt");
public Form1()
{
InitializeComponent();
for (int x = 0; x <= 8939500; x++)
{
lineuser = fileuser.ReadLine();
string[] values = lineuser.Split(' '); //<------the line's error
int userid, factoriduser;
foreach (string value in values)
{
userid = Convert.ToInt32(values[0]);
factoriduser = Convert.ToInt32(values[1]);
userscore = Convert.ToSingle(values[2]);
a[userid][factoriduser] = userscore;
}
}
for (int y = 0; y <= 114360000; y++)
{
lineitem = fileitem.ReadLine();
string[] valuesi = lineitem.Split(' ');
int itemid, factoriditem;
foreach (string value in valuesi)
{
itemid = Convert.ToInt32(valuesi[0]);
factoriditem = Convert.ToInt32(valuesi[1]);
itemscore = Convert.ToSingle(valuesi[2]);
b[itemid][factoriditem] = itemscore;
}
}
}
public float dotproduct(int userid,int itemid)
{
//get the score of 100 from user and item to dotproduct
float[] u_f = a[userid];
float[] i_f = b[itemid];
for (int i = 0; i <u_f.GetLength(1); i++)
{
result += u_f[userid] * i_f[itemid];
}
return result;
}
private void btn_recomm_Click(object sender, EventArgs e)
{
if(txtbx_id.Text==null)
{
MessageBox.Show("please insert user id");
}
if (txtbx_id.Text != null && txtbx_itemid==null)
{
int sc = Convert.ToInt32(txtbx_id.Text);
if (sc>=0 &&sc<=89395)
{
for (int z=0;z<=1143600;z++)
{
dotproduct(sc,z);
}
//Hashtable hashtable = new Hashtable();
//put the result in hashtable
//foreach (DictionaryEntry entry in hashtable)
//{
//Console.WriteLine("{0}, {1}", entry.Key, entry.Value);
// }
}
}
if (txtbx_id!=null &&txtbx_itemid!=null)
{
int uid = Convert.ToInt32(txtbx_id.Text);
int iid = Convert.ToInt32(txtbx_itemid.Text);
{
if (uid>=0 && uid<=89395 && iid>=0 && iid<=1143600)
{
dotproduct(uid,iid);
MessageBox.Show("The Score of user id "+uid+" is "+result);
}
}
Please check you lineuser variable is null
public Form1()
{
InitializeComponent();
for (int x = 0; x <= 8939500; x++)
{
if(!string.IsNullorEmpty(lineuser) //<--- check the string is empty
{
string[] values = lineuser.Split(' '); //<------the line's error
int userid, factoriduser;
foreach (string value in values)
{
userid = Convert.ToInt32(values[0]);
factoriduser = Convert.ToInt32(values[1]);
userscore = Convert.ToSingle(values[2]);
a[userid][factoriduser] = userscore;
}
}
}
for (int y = 0; y <= 114360000; y++)
{
lineitem = fileitem.ReadLine();
if(!string.IsNullorEmpty(lineitem) //<--- check the string is empty
{
string[] valuesi = lineitem.Split(' ');
int itemid, factoriditem;
foreach (string value in valuesi)
{
itemid = Convert.ToInt32(valuesi[0]);
factoriditem = Convert.ToInt32(valuesi[1]);
itemscore = Convert.ToSingle(valuesi[2]);
b[itemid][factoriditem] = itemscore;
}
}
}
}
Now you can avoid the error.
You haven't opened the Stream fileuser so it is still null.
It is really a bad practice to open the file while you define the global variable in your class.
But as part from this, when you call ReadLine the result could be a null because there are no more lines to read and you don't check for this case.
Looking at the code shown above, there is no need to have a global variable for the filestream, so, the usual pattern when handling resources (OPEN/USE/CLOSE) should be followed for both files
public Form1()
{
InitializeComponent();
string lineuser;
// OPEN
using(StreamReader fileuser = new StreamReader("c:\\USER_SVD_FULL.txt"))
{
// USE
while((lineuser = fileuser.ReadLine()) != null)
{
string[] values = lineuser.Split(' ');
....
}
} //CLOSE & DISPOSE
....
string lineitem;
using(StreamReader fileitem = new StreamReader("c:\\ITEM_SVD_FULL.txt"))
{
while((lineitem = fileitem.ReadLine()) != null)
{
string[] valuesi = lineitem.Split(' ');
....
}
}

Removing More Than Two Duplicates From A List

I'm trying to figure out the best way to remove duplicates from a list in C#. However I want to keep two of the duplicated entries (two total identical entries) while removing all of the rest. I've seen plenty of examples of removing all duplicates from a list, but my specific issue seems to be less common.
This is the majority of my code. The background is this is a debate scheduler project for a class I'm in. I research a few ways to delete duplicates and found many on here but not with my stipulations. Each team can only debate twice per day and no more and they are assigned randomly to there debate times leading to my problem of them being assigned more than two times per scheduled day.
The teams are being assigned randomly and then moved to a list, so by duplicates I mean I'm trying to remove all dupes after the initial two if they exist at all.
Thanks and sorry for the ambiguity.
namespace SWEProject3
{
public partial class DebateSchedulerForm : Form
{
//There are 10 slots for team names
//The names can only be edited by the superadmin
static int ADMIN = 1;
static int GUEST = 2;
public List<string> nameList = new List<string>();
public List<string> winList = new List<string>();
public List<string> lossList = new List<string>();
public List<string> dateList = new List<string>();
public List<string> debateList = new List<string>();
public List<string> week1List = new List<string>();
public List<string> week2List = new List<string>();
public List<string> week3List = new List<string>();
public List<string> week4List = new List<string>();
public List<string> week5List = new List<string>();
public List<string> week6List = new List<string>();
public List<string> week7List = new List<string>();
public List<string> week8List = new List<string>();
public List<string> week9List = new List<string>();
public List<string> week10List = new List<string>();
public DebateSchedulerForm(int x)
{
InitializeComponent();
initNames();
initWin();
initLoss();
initDates();
initDebates();
initWeekLists();
ListNames();
ListWin();
ListLoss();
ListDates();
if (x == ADMIN || x == GUEST)
{
Name1.ReadOnly = true;
Name2.ReadOnly = true;
Name3.ReadOnly = true;
Name4.ReadOnly = true;
Name5.ReadOnly = true;
Name6.ReadOnly = true;
Name7.ReadOnly = true;
Name8.ReadOnly = true;
Name9.ReadOnly = true;
Name10.ReadOnly = true;
Win1.ReadOnly = true;
Win2.ReadOnly = true;
Win3.ReadOnly = true;
Win4.ReadOnly = true;
Win5.ReadOnly = true;
Win6.ReadOnly = true;
Win7.ReadOnly = true;
Win8.ReadOnly = true;
Win9.ReadOnly = true;
Win10.ReadOnly = true;
Loss1.ReadOnly = true;
Loss2.ReadOnly = true;
Loss3.ReadOnly = true;
Loss4.ReadOnly = true;
Loss5.ReadOnly = true;
Loss6.ReadOnly = true;
Loss7.ReadOnly = true;
Loss8.ReadOnly = true;
Loss9.ReadOnly = true;
Loss10.ReadOnly = true;
ChangeDates.Visible = false;
Save.Visible = false;
}
}
public void Shuffle()
{
Random gen = new Random();
int n = debateList.Count();
while (n > 1)
{
n--;
int k = gen.Next(n + 1);
string value = debateList[k];
debateList[k] = debateList[n];
debateList[n] = value;
}
}
public void ListNames()
{
this.Name1.Text = nameList[0];
this.Name2.Text = nameList[1];
this.Name3.Text = nameList[2];
this.Name4.Text = nameList[3];
this.Name5.Text = nameList[4];
this.Name6.Text = nameList[5];
this.Name7.Text = nameList[6];
this.Name8.Text = nameList[7];
this.Name9.Text = nameList[8];
this.Name10.Text = nameList[9];
}
public void ListWin()
{
this.Win1.Text = winList[0];
this.Win2.Text = winList[1];
this.Win3.Text = winList[2];
this.Win4.Text = winList[3];
this.Win5.Text = winList[4];
this.Win6.Text = winList[5];
this.Win7.Text = winList[6];
this.Win8.Text = winList[7];
this.Win9.Text = winList[8];
this.Win10.Text = winList[9];
}
public void ListLoss()
{
this.Loss1.Text = lossList[0];
this.Loss2.Text = lossList[1];
this.Loss3.Text = lossList[2];
this.Loss4.Text = lossList[3];
this.Loss5.Text = lossList[4];
this.Loss6.Text = lossList[5];
this.Loss7.Text = lossList[6];
this.Loss8.Text = lossList[7];
this.Loss9.Text = lossList[8];
this.Loss10.Text = lossList[9];
}
public void ListDates()
{
this.Date1.Text = dateList[0];
this.Date2.Text = dateList[1];
this.Date3.Text = dateList[2];
this.Date4.Text = dateList[3];
this.Date5.Text = dateList[4];
this.Date6.Text = dateList[5];
this.Date7.Text = dateList[6];
this.Date8.Text = dateList[7];
this.Date9.Text = dateList[8];
this.Date10.Text = dateList[9];
}
public void initNames()
{
StreamReader sr = new StreamReader("nameList.txt");
for (int i = 0; i < 10; i++)
{
string line = sr.ReadLine();
nameList.Add(line);
}
sr.Close();
}
public void initWin()
{
StreamReader sw = new StreamReader("Win.txt");
for (int i = 0; i < 10; i++)
{
string line = sw.ReadLine();
winList.Add(line);
}
sw.Close();
}
public void initLoss()
{
StreamReader sw = new StreamReader("Loss.txt");
for (int i = 0; i < 10; i++)
{
string line = sw.ReadLine();
lossList.Add(line);
}
sw.Close();
}
public void initDates()
{
StreamReader sw = new StreamReader("Dates.txt");
for (int i = 0; i < 10; i++)
{
string line = sw.ReadLine();
dateList.Add(line);
}
sw.Close();
}
public void initDebates()
{
StreamReader sw = new StreamReader("Debate.txt");
for (int i = 0; i < 45; i++)
{
string line = sw.ReadLine();
debateList.Add(line);
}
sw.Close();
}
public void initWeekLists()
{
week1List.Add(debateList[0]);
week1List.Add(debateList[1]);
week1List.Add(debateList[2]);
week1List.Add(debateList[3]);
week1List.Add(debateList[4]);
week2List.Add(debateList[5]);
week2List.Add(debateList[6]);
week2List.Add(debateList[7]);
week2List.Add(debateList[8]);
week2List.Add(debateList[9]);
week3List.Add(debateList[10]);
week3List.Add(debateList[11]);
week3List.Add(debateList[12]);
week3List.Add(debateList[13]);
week3List.Add(debateList[14]);
week4List.Add(debateList[15]);
week4List.Add(debateList[16]);
week4List.Add(debateList[17]);
week4List.Add(debateList[18]);
week4List.Add(debateList[19]);
week5List.Add(debateList[20]);
week5List.Add(debateList[21]);
week5List.Add(debateList[22]);
week5List.Add(debateList[23]);
week5List.Add(debateList[24]);
week6List.Add(debateList[25]);
week6List.Add(debateList[26]);
week6List.Add(debateList[27]);
week6List.Add(debateList[28]);
week7List.Add(debateList[29]);
week7List.Add(debateList[30]);
week7List.Add(debateList[31]);
week7List.Add(debateList[32]);
week8List.Add(debateList[33]);
week8List.Add(debateList[34]);
week8List.Add(debateList[35]);
week8List.Add(debateList[36]);
week9List.Add(debateList[37]);
week9List.Add(debateList[38]);
week9List.Add(debateList[39]);
week9List.Add(debateList[40]);
week10List.Add(debateList[41]);
week10List.Add(debateList[42]);
week10List.Add(debateList[43]);
week10List.Add(debateList[44]);
}
public void finNames()
{
StreamWriter sw = new StreamWriter("nameList.txt");
sw.WriteLine(this.Name1.Text);
sw.WriteLine(this.Name2.Text);
sw.WriteLine(this.Name3.Text);
sw.WriteLine(this.Name4.Text);
sw.WriteLine(this.Name5.Text);
sw.WriteLine(this.Name6.Text);
sw.WriteLine(this.Name7.Text);
sw.WriteLine(this.Name8.Text);
sw.WriteLine(this.Name9.Text);
sw.WriteLine(this.Name10.Text);
sw.Close();
}
public void finWin()
{
StreamWriter sw = new StreamWriter("Win.txt");
sw.WriteLine(this.Win1.Text);
sw.WriteLine(this.Win2.Text);
sw.WriteLine(this.Win3.Text);
sw.WriteLine(this.Win4.Text);
sw.WriteLine(this.Win5.Text);
sw.WriteLine(this.Win6.Text);
sw.WriteLine(this.Win7.Text);
sw.WriteLine(this.Win8.Text);
sw.WriteLine(this.Win9.Text);
sw.WriteLine(this.Win10.Text);
sw.Close();
}
public void finLoss()
{
StreamWriter sw = new StreamWriter("Loss.txt");
sw.WriteLine(this.Loss1.Text);
sw.WriteLine(this.Loss2.Text);
sw.WriteLine(this.Loss3.Text);
sw.WriteLine(this.Loss4.Text);
sw.WriteLine(this.Loss5.Text);
sw.WriteLine(this.Loss6.Text);
sw.WriteLine(this.Loss7.Text);
sw.WriteLine(this.Loss8.Text);
sw.WriteLine(this.Loss9.Text);
sw.WriteLine(this.Loss10.Text);
sw.Close();
}
public void finDebates()
{
StreamWriter sw = new StreamWriter("Debate.txt");
for (int i = 0; i < 45; i++)
{
sw.WriteLine(debateList[i]);
}
sw.Close();
}
private void Save_Click(object sender, EventArgs e)
{
finNames();
finWin();
finLoss();
finDebates();
}
private void Close_Click(object sender, EventArgs e)
{
this.Close();
}
private void ChangeDates_Click(object sender, EventArgs e)
{
ChangeDates form = new ChangeDates(dateList);
form.ShowDialog();
initDates();
ListDates();
}
private void Date1_Click(object sender, EventArgs e)
{
Week_1 form = new Week_1(nameList, week1List);
form.ShowDialog();
}
private void Date2_Click(object sender, EventArgs e)
{
Week_2 form = new Week_2(nameList, week2List);
form.ShowDialog();
}
}
}
Assuming the debateList is the list you'd like to filter:
public List<string> debateList = new List<string>();
You can use Linq's GroupBy method chained with the SelectMany method and take advantage of the Take method which will take up to the max specified even if less are present:
List<string> result = debateList.GroupBy( x => x )
.SelectMany( x => x.Take( 2 ) )
.OrderBy( x => x )
.ToList()
You could set a counting variable, loop through the container and increment the counter each time an element is present in the container.

I have a CSV file where the Date and the time are into 2 fields. How can I use FileHelpers to aggregate the 2 fields into the same DateTime data?

I have a CSV file where the Date and the time are into 2 fields.
How can I use FileHelpers to aggregate the 2 fields into the same DateTime data ?
Thanks,
2011.01.07,09:56,1.2985,1.2986,1.2979,1.2981,103
2011.01.07,09:57,1.2981,1.2982,1.2979,1.2982,75
2011.01.07,09:58,1.2982,1.2982,1.2976,1.2977,83
2011.01.07,09:59,1.2977,1.2981,1.2977,1.2980,97
2011.01.07,10:00,1.2980,1.2980,1.2978,1.2979,101
2011.01.07,10:01,1.2980,1.2981,1.2978,1.2978,57
2011.01.07,10:02,1.2978,1.2979,1.2977,1.2978,86
2011.01.07,10:03,1.2978,1.2978,1.2973,1.2973,84
2011.01.07,10:04,1.2973,1.2976,1.2973,1.2975,71
2011.01.07,10:05,1.2974,1.2977,1.2974,1.2977,53
2011.01.07,10:06,1.2977,1.2979,1.2976,1.2978,57
2011.01.07,10:07,1.2978,1.2978,1.2976,1.2976,53
2011.01.07,10:08,1.2976,1.2980,1.2976,1.2980,58
2011.01.07,10:09,1.2979,1.2985,1.2979,1.2980,63
var file = #"2011.01.07,09:56,1.2985,1.2986,1.2979,1.2981,103
2011.01.08,09:57,1.2981,1.2982,1.2979,1.2982,75
2011.01.09,09:58,1.2982,1.2982,1.2976,1.2977,83
2011.01.07,09:59,1.2977,1.2981,1.2977,1.2980,97
2011.01.07,10:00,1.2980,1.2980,1.2978,1.2979,101
2011.01.07,10:01,1.2980,1.2981,1.2978,1.2978,57
2011.01.07,10:02,1.2978,1.2979,1.2977,1.2978,86
2011.01.07,10:03,1.2978,1.2978,1.2973,1.2973,84
2011.01.07,10:04,1.2973,1.2976,1.2973,1.2975,71
2011.01.07,10:05,1.2974,1.2977,1.2974,1.2977,53
2011.01.07,10:06,1.2977,1.2979,1.2976,1.2978,57
2011.01.07,10:07,1.2978,1.2978,1.2976,1.2976,53
2011.01.07,10:08,1.2976,1.2980,1.2976,1.2980,58
2011.01.07,10:09,1.2979,1.2985,1.2979,1.2980,63";
var rows = file.Split('\n');
foreach(var row in rows){
var cols = row.Split(',');
var col1 = new DateTime();
foreach(var col in cols){
if (col == cols[0]) // first col
{
var dateParts = col.Split('.');
col1 = new DateTime(int.Parse(dateParts[0]), int.Parse(dateParts[1]), int.Parse(dateParts[2]));
}
else if (col == cols[1]) // second col
{
var timeParts = col.Split(':');
col1 = col1.AddHours(int.Parse(timeParts[0]));
col1 = col1.AddMinutes(int.Parse(timeParts[1]));
//col1.Dump();
}
else {
// all other columns here
}
}
}
I answer my own question.
Because my need have change, I dont really answer my own question.
My question have evolve to :
I have a CSV file where the Date and the time are into 2 fields. How can I use FileHelpers to aggregate the 2 fields into the same XLDate data ?
Here the full projet where I use this code :
enter link description here
private void CreateGraphic(ZedGraphControl zgc)
{
// référence vers le "canevas"
GraphPane pane = zgc.GraphPane;
pane.Title.Text = "Japanese Candlestick Chart Demo";
pane.XAxis.Title.Text = "Trading Date";
pane.YAxis.Title.Text = "Share Price, $US";
FileHelperEngine<MetaTrader4> engine = new FileHelperEngine<MetaTrader4>();
engine.ErrorManager.ErrorMode = ErrorMode.SaveAndContinue;
MetaTrader4[] res = engine.ReadFile(#"..\..\Data\EURUSD240.csv");
if (engine.ErrorManager.ErrorCount > 0)
engine.ErrorManager.SaveErrors("Errors.txt");
StockPointList spl = new StockPointList();
foreach (MetaTrader4 quotes in res)
{
DateTime dateTime = new DateTime();
dateTime = DateTime.ParseExact(quotes.Date + "-" + quotes.Time, "yyyy.MM.dd-HH:mm",
null);
XDate xDate = new XDate(dateTime);
StockPt pt = new StockPt(xDate, quotes.Hight, quotes.Low, quotes.Open, quotes.Close, quotes.Volume);
spl.Add(pt);
}
JapaneseCandleStickItem myCurve = pane.AddJapaneseCandleStick("trades", spl);
myCurve.Stick.IsAutoSize = true;
myCurve.Stick.Color = Color.Blue;
// Use DateAsOrdinal to skip weekend gaps
pane.XAxis.Type = AxisType.DateAsOrdinal;
// pretty it up a little
pane.Chart.Fill = new Fill(Color.White, Color.LightGoldenrodYellow, 45.0f);
pane.Fill = new Fill(Color.White, Color.FromArgb(220, 220, 255), 45.0f);
zgc.AxisChange();
}
You do this by listening to the engine.BeforeReadRecord event.
As you (engine) read each line, you'll need to remove the delimiter between the date and time so that it fits the expected date time format you specified in the FieldConverter attribute.
Here's is a linqpad snippet to demonstrate.
void Main()
{
string reading = "2011.01.07,09:56,1.2985,1.2986,1.2979,1.2981,103";
var engine = new FileHelperEngine<Reading>();
//engine.Options.Fields.Dump();
char delimiter = ((DelimitedRecordOptions)engine.Options).Delimiter.ToCharArray().First();
int expectedDelimiterCount = engine.Options.Fields.Sum(field => field.FieldType == typeof(DateTime) ? 2 : field.ArrayMinLength == 0 ? 1 : field.ArrayMinLength);
expectedDelimiterCount--; // no ending delimiter
engine.BeforeReadRecord += (ngin, e) => {
int fieldCount = e.RecordLine.Count(c => c == delimiter);
if (fieldCount == expectedDelimiterCount)
{
int delimiterIndex = e.RecordLine.IndexOf(delimiter);
if (delimiterIndex > NOT_FOUND)
{
e.RecordLine = e.RecordLine.Remove(delimiterIndex, 1);
}
}
};
var readings = engine.ReadString(reading);
readings.Dump();
}
const int NOT_FOUND = -1;
// Define other methods and classes here
[DelimitedRecord(",")]
class Reading
{
[FieldOrder(1)]
[FieldConverter(ConverterKind.Date, "yyyy.MM.ddHH:mm")]
public DateTime CollectionDate { get; set; }
[FieldOrder(2)]
[FieldArrayLength(4)]
public decimal[] Data;
[FieldOrder(3)]
public int CollectorID { get; set; }
}
Writing out the DateTime property into two fields is left as an exercise for the reader.

Categories