I have to remove duplicate rows in a array using id using C#. In the array I have 3 columns.
Following is my code
[WebMethod]
public static string GetYesterdayPatientsByTime()
{
try
{
BusinessLogicLayer bal = new BusinessLogicLayer();
DataSet ds = bal.GetYesterdayPatientsByTimeBAL();
string[] output = new string[(ds.Tables[0].Rows.Count * ds.Tables[0].Columns.Count)];
int count = 0;
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
for (int j = 0; j < ds.Tables[0].Columns.Count; j++)
{
output[count++] = ds.Tables[0].Rows[i].ItemArray[j].ToString();
}
}
JavaScriptSerializer js = new JavaScriptSerializer();
js.MaxJsonLength = 2147483644;
return js.Serialize(output.Distinct().ToArray());
}
catch (Exception)
{
return "";
throw;
}
}
You can expand the Distinct() method into DistinctBy(), which will allow You to distinct by several columns - check link: LINQ's Distinct() on a particular property
Another solution that came in my mind is create ArrayList with the results. While going through whole array, You will check if the element does exist in list, and if not You will add it.
After checking MSDN - https://msdn.microsoft.com/cs-cz/library/bb348436(v=vs.110).aspx - You can find that Distinct() by default using Default IEquatable, so You can also add own Comparer to the class, which will compare based on ID.
Related
User can pass any number of list with same number of elements in it. Example- user has passed below 3 (could be dynamic with same number of elements in it) list -
hospitalId - H11, H12, H13...n
patientId - P11, P12, P13...n
statusId - S11, S13, S11...n
What is the efficient way of creating a set out of it and storing it as a string in below format? Need a c# code for it.
expected output -
"((H11,P11, S11), (H12, P12, S13), (H13, P13, S11))"
You should iterate through your list and append them index wise to prepare the result.
StringBuilder builder = new StringBuilder();
builder.Append("(");
for(var index = 0; index < n; index++)
{
builder.AppendFormat("({0}, {1}, {2})", hospitalId[index], patientId[index], statusId[index]);
}
builder.Append(")");
var result = builder.ToString();
If you have n number of List<T> items with the same length, a basic loop will do the trick. Here's a version as an extension method that will take any number of lists as an input:
public static IEnumerable<IEnumerable<T>> ZipMultiple<T>(this List<List<T>> source)
{
var counts = source.Select(s => s.Count).Distinct();
if (counts.Count() != 1)
{
throw new ArgumentException("Lists aren't the same length");
}
for (var i = 0; i < counts.First(); i++)
{
var item = new List<T>();
for (var j = 0; j < source.Count; j++)
{
item.Add(source[j][i]);
}
yield return item;
}
}
After that, it's pretty simple to convert the result into a string in another loop, or you can do it as a single liner:
var zipped = lists.ZipMultiple();
var output = $"({string.Join(", ", zipped.Select(x => $"({string.Join(",", x)})"))})";
I need to push the result into an array to be able to display in a chart . I am keep getting System.Data.DataRow instead of the value. I need to know, the proper way to store the result(currently I store it in DataTable), and to push it into an array.I am newbie in c# ..
public void getOutstanding()
{
SelectQueryBuilder sqbSelect;
DataSet dsOutstanding;
sqbSelect = new SelectQueryBuilder();
sqbSelect.SelectColumns(new string[] { "name"});
sqbSelect.SelectFromTable("user");
sqbSelect.AddWhere("category", Comparison.Equals, "18");
dsOutstanding = Conn.DataAdapter(CommandType.Text, sqbSelect.BuildQuery());
sqbSelect = null;
DataTable areaChart = dsOutstanding.Tables[0];
for( int a = 0; a < areaChart.Rows.Count; a++) {
// want to push the value to an array ;
}
}
Thank you..
You can read by using this syntax.
string[] array = new string[areaChart.Rows.Count];
for( int a = 0; a < areaChart.Rows.Count; a++) {
array[a] = areaChart.Rows[a]["name"].ToString();
}
You can access column data by indexing DataRow with column name
var names = new string[areaChart.Rows.Count];
for (var index = 0; index < areaChart.Rows.Count; index++)
names[index] = areaChart.Rows[index]["name"].ToString();
I am planning to get an array of the averages of each column.
But my app crashes at sum[j] += int.Parse(csvArray[i,j]); due to a FormatException. I have tried using Convert.ToDouble and Double.Parse but it still throws that exception.
The increments in the for loop start at 1 because Row 0 and Column 0 of the CSV array are strings (names and timestamps). For the divisor or total count of the fields that have values per column, I only count the fields that are not BLANK, hence the IF statement. I think I need help at handling the exception.
Below is the my existing for the method of getting the averages.
public void getColumnAverages(string filePath)
{
int col = colCount(filePath);
int row = rowCount(filePath);
string[,] csvArray = csvToArray(filePath);
int[] count = new int[col];
int[] sum = new int[col];
double[] average = new double[col];
for (int i = 1; i < row; i++)
{
for (int j = 1; j < col; j++)
{
if (csvArray[i,j] != " ")
{
sum[j] += int.Parse(csvArray[i,j]);
count[j]++;
}
}
}
for (int i = 0; i < average.Length; i++)
{
average[i] = (sum[i] + 0.0) / count[i];
}
foreach(double d in average)
{
System.Diagnostics.Debug.Write(d);
}
}
}
I have uploaded the CSV file that I use when I test the prototype. It has BLANK values on some columns. Was my existing IF statement unable to handle that case?
There are also entries like this 1.324556-e09due to the number of decimals I think. I guess I have to trim it in the csvToArray(filePath) method or are there other efficient ways? Thanks a million!
So there are a few problems with your code. The main reason for your format exception is that after looking at your CSV file your numbers are surrounded by quotes. Now I can't see from your code exactly how you convert your CSV file to an array but I'm guessing that you don't clear these out - I didn't when I first ran with your CSV and experienced the exact same error.
I then ran into an error because some of the values in your CSV are decimal, so the datatype int can't be used. I'm assuming that you still want the averages of these columns so in my slightly revised verion of your method I change the arrays used to be of type double.
AS #musefan suggested, I have also changed the check for empty places to use the IsNullOrWhiteSpace method.
Finally when you output your results you receive a NaN for the first value in the averages column, this is because when you don't take into account that you never populate the first position of your arrays so as not to process the string values. I'm unsure how you'd best like to correct this behaviour as I'm not sure of the intended purpose - this might be okay - so I've not made any changes to this for the moment, pop a mention in the comments if you want help on how to sort this!
So here is the updated method:
public static void getColumnAverages(string filePath)
{
// Differs from the current implementation, reads a file in as text and
// splits by a defined delim into an array
var filePaths = #"C:\test.csv";
var csvArray = File.ReadLines(filePaths).Select(x => x.Split(',')).ToArray();
// Differs from the current implementation
var col = csvArray[0].Length;
var row = csvArray.Length;
// Update variables to use doubles
double[] count = new double[col];
double[] sum = new double[col];
double[] average = new double[col];
Console.WriteLine("Started");
for (int i = 1; i < row; i++)
{
for (int j = 1; j < col; j++)
{
// Remove the quotes from your array
var current = csvArray[i][j].Replace("\"", "");
// Added the Method IsNullOrWhiteSpace
if (!string.IsNullOrWhiteSpace(current))
{
// Parse as double not int to account for dec. values
sum[j] += double.Parse(current);
count[j]++;
}
}
}
for (int i = 0; i < average.Length; i++)
{
average[i] = (sum[i] + 0.0) / count[i];
}
foreach (double d in average)
{
System.Diagnostics.Debug.Write(d + "\n");
}
}
I have a C# console window program and I am trying to sort "File3" (contains numbers) in ascending and output lines from 3 text files.
So the outcome looks something like this:
===========================================================================
field1.....................field2.....................field3
===========================================================================
[FILE1_LINE1]..............[FILE2_LINE1]..............[FILE3_LINE1]
[FILE1_LINE2]..............[FILE2_LINE2]..............[FILE3_LINE2]
[FILE1_LINE3]..............[FILE2_LINE3]..............[FILE3_LINE3]
and so on...
At the moment, it kinda works I think but it duplicates the first two lines it seems. Could someone give an example of better coding please?
Here is the code that I have atm:
string[] File1 = System.IO.File.ReadAllLines(#"FILE1.txt");
string[] File2 = System.IO.File.ReadAllLines(#"FILE2.txt");
string[] File3 = System.IO.File.ReadAllLines(#"FILE3.txt");
decimal[] File3_1 = new decimal[File3.Length];
for(int i=0; i<File3.Length; i++)
{
File3_1[i] = decimal.Parse(File3[i]);
}
decimal[] File3_2 = new decimal[File3.Length];
for(int i=0; i<File3.Length; i++)
{
File3_2[i] = decimal.Parse(File3[i]);
}
decimal number = 0;
for (double i = 0.00; i < File3_1.Length; i++)
{
for (int sort = 0; sort < File3_1.Length - 1; sort++)
{
if (File3_1[sort] > File3_1[sort + 1])
{
number = File3_1[sort + 1];
File3_1[sort + 1] = File3_1[sort];
File3_1[sort] = number;
}
}
}
if (SortChoice2 == 1)
{
for (int y = 0; y < File3_2.Length; y++)
{
for (int s = 0; s < File3_2.Length; s++)
{
if (File3_1[y] == File3_2[s])
{
Console.WriteLine(File1[s] + File2[s] + File3_1[y]);
}
}
}
}
Just for more info, most of this code was used for another program and worked but in my new program, this doesn't as I've said above - ("it repeats a couple of lines for some reason"). I'm kinda an amateur/ rookie at C# so I only get stuff like this to work with examples.
Thanks in advance :)
Ok, if I understand correctly, what you are trying to do is read the lines from 3 different files, each of them representing a different "field" in a table. You then want to sort this table based on the value of one of the field (in you code, this seems to be the field which values are contained in File3. Well, if I got that right, here's what I suggest you do:
// Read data from files
List<string> inputFileNames = new List<string> {"File1.txt", "File2.txt", "File3.txt"};
decimal[][] fieldValues = new decimal[inputFileNames.Count][];
for (int i = 0; i < inputFileNames.Count; i++)
{
string currentInputfileName = inputFileNames[i];
string[] currentInputFileLines = File.ReadAllLines(currentInputfileName);
fieldValues[i] = new decimal[currentInputFileLines.Length];
for (int j = 0; j < currentInputFileLines.Length; j++)
{
fieldValues[i][j] = decimal.Parse(currentInputFileLines[j]);
}
}
// Create table
DataTable table = new DataTable();
DataColumn field1Column = table.Columns.Add("field1", typeof (decimal));
DataColumn field2Column = table.Columns.Add("field2", typeof (decimal));
DataColumn field3Column = table.Columns.Add("field3", typeof (decimal));
for (int i = 0; i < fieldValues[0].Length; i++)
{
var newTableRow = table.NewRow();
newTableRow[field1Column.ColumnName] = fieldValues[0][i];
newTableRow[field2Column.ColumnName] = fieldValues[1][i];
newTableRow[field3Column.ColumnName] = fieldValues[2][i];
table.Rows.Add(newTableRow);
}
// Sorting
table.DefaultView.Sort = field1Column.ColumnName;
// Output
foreach (DataRow row in table.DefaultView.ToTable().Rows)
{
foreach (var item in row.ItemArray)
{
Console.Write(item + " ");
}
Console.WriteLine();
}
Now, I tried to keep the code above as LINQ free as I could, since you do not seem to be using it in your example, and therefore might not know about it. That being said, while there is a thousand way to do I/O in C#, LINQ would help you a lot in this instance (and in pretty much any other situation really), so I suggest you look it up if you don't know about it already.
Also, the DataTable option I proposed is just to provide a way for you to visualize and organize the data in a more efficient way. That being said, you are in no way obliged to use a DataTable: you could stay with a more direct approach and use more common data structures (such as lists, arrays or even dictionaries if you know what they are) to store the data, depending on your needs. It's just that with a DataTable, you don't, for example, need to do the sorting yourself, or deal with columns indexed only by integers. With time, you'll come to learn about the myriad of useful data structure and native functionalities the C# language offers you and how they can save you doing the work yourself in a lot of cases.
I am using the following code in C#. I am adding the values into the arraylist by using index. Now I want to read the values from the arraylist by using the index only. In the following example I am simply reading all the values from the arrylist but I want to read the values from the arrylist based on index( for e.g Customer_Details[i]) for each element at index i.
public struct Cust_Info
{
public String Client_Key;
public String Registration_Key;
public int Standard;
public Cust_Info(String C_Key, String Reg_Key, int Std)
{
Client_Key = C_Key;
Registration_Key = Reg_Key;
Standard = Std;
}
}
private void Form1_Load(object sender, EventArgs e)
{
ArrayList Customer_Details = new ArrayList();
for (int i = 0; i < 1; i++)
{
Customer_Details.Insert(i, new Cust_Info("A", "B", 1));
}
//for (int i = 0; i < 1; i++)
//{
Customer_Details.Insert(1, new Cust_Info("C", "D", 2));
for (int i = 0; i < 1; i++)
{
ArrayList obj=new ArrayList();
//((ArrayListOFStructures.Form1.Cust_Info)((new System.Collections.ArrayList.ArrayListDebugView(Customer_Details)).Items[0])).Client_Key
//obj = (ArrayList)Customer_Details[i];
foreach (Cust_Info temp in Customer_Details)
{
//comboBox1.Items.Add(Customer_Details[0].ToString());
comboBox1.Items.Add(temp.Client_Key);
comboBox1.Items.Add(temp.Registration_Key);
comboBox1.Items.Add(temp.Standard);
}
}
}
In the above code i want to make the use the structure only. How can I read the values from the arrylist based on index. Can you please provide me any code or link through which I can resolve the above issue ?
I'm confused; you can get an item out of an ArrayList by index simply by:
Cust_Info cust = (CustInfo)theList[index];
However, ArrayList is pretty rare in anything >= .NET 2.0, a List<Cust_Info> would make this much easier. Also, Cust_Info looks to me very much like it should be a class (it is very rare to write a struct in .NET, and usually to denote "values" - a customer isn't a "value"). And public fields are also very much discouraged.
Note that currently you are (because it is a struct) actually copying the Cust_Info whenever you fetch it from (or place it in) the list; that isn't necessarily what you intend...
You can try something like
ArrayList arr = new ArrayList();
for (int iIndex = 0; iIndex < arr.Count; iIndex++)
{
object o = arr[iIndex];
}
But I would rather go with
List Class and List.Count Property
for(int i=0; i<Customer_Details.Count/*or.Length*/; i++)
Customer_Details[i] = something;