Say I want to create (n) DataTables named DT(n)... how can I go about that in a loop.
Pseudo code below
int n=99;
for (int i = 0; i < n; i++)
{
DataTable DT + n = new DataTable(); // <--- this
}
Is this possible?
Store them in a data structure.
Enumerable.Range(0,n).Select(x => new DataTable()).ToArray()
No, you can't have dynamic variable names in C#.
You can however, put them into an array (this is a much better approach anyways):
int n=99;
DataTable[] DT = new DataTable[99];
for (int i = 0; i < n; i++)
{
DT[i] = new DataTable();
}
You can't create dynamically named variables in C#.
For your purpose you are better off using Arrays or Dictionaries ( http://msdn.microsoft.com/en-us/library/xfhwa508%28v=vs.110%29.aspx )
try
List<DataTable> DTs = new List<DataTable>();
int n =99;
for(int(i=0;i<n;i++)
{
DataTable DT = new DataTable();
DTs.Add(DT);
}
Can you try this one
public List<T> CreateObjects<T>(int numbers) where T: new()
{
List<T> _return = new List<T>();
for (int i = 0; i <= numbers; i++)
{
_return.Add(new T());
}
return _return;
}
to use
var myList = CreateObjects<DataTable>(100);
var myList = CreateObjects<AnyClass>(100);
use any object type
Related
I am getting the index of the cell of a word table using for loop which takes a lot of time for bigger tables, is there any way to do this without for loop?
public static int[] GetColumnIndex(Xceed.Words.NET.Table table, string columnName, int endRow,int k)
{
int[] data = { -1, -1 };
for (int j = k; j < endRow; j++)
{
for (int i = 0; i < table.Rows[j].Cells.Count; ++i)
{
if (table.Rows[j].Cells[i].Paragraphs[0].Text.Equals("«" + columnName + "»"))
{
data[0] = j;
data[1] = i;
return data;
}
}
}
return data;
}
and I am calling this function form another function
int startRow = 0, endRow = 0;
int[] ind;
DocX doc;
doc = DocX.Load(fileName);
Xceed.Words.NET.Table t;
t = doc.Tables[0];
endRow = t.Rows.Count;
System.Data.DataTable dt = new DataTable();
dt = reader(report.Query);
foreach (DataColumn col in dt.Columns)
{
ind = GetColumnIndex(t, col.ColumnName, endRow,2);
//...more code here...
}
A few things you can do to optimise your algorithm (based on your access pattern) is that you search the same table number of times (in fact, since you are searching column names in the table, number of searches increases quickly as the table gets big). Hence, it would be worth transforming the data in the table to a data structure indexed by the words (for e.g. a Sorted Dictionary).
Firstly, create a class that holds the content of the table. This way when you want to search the same table, you can use the same instance of the class and avoid recreating the data structure based on the sorted dictionary:
public class XceedTableAdapter
{
private readonly SortedDictionary<string, (int row, int column)> dict;
public XceedTableAdapter(Xceed.Words.NET.Table table)
{
this.dict = new SortedDictionary<string, (int, int)>();
// Copy the content of the table into the dict.
// If you have duplicate words you need a SortedDictionary<string, List<(int, int)>> type. This is not clear in your question.
for (var i = 0, i < rowCount; i++)
{
for (var j = 0; j < columnCount; j++)
{
// this will overwrite the index if the text was previously found:
this.dict[table.Rows[i].Cells[j].Paragraphs[0].Text] = (i, j);
}
}
}
public (int, int) GetColumnIndex(string searchText)
{
if(this.dict.TryGetValue(searchText, out var index))
{
return index;
}
return (-1, -1);
}
}
Now you loop the entire table only once and the subsequent searches will happen in O(log n). If Xceed has a function to transform data table to a dictionary, that would be quite handy. I'm not familiar with this library.
Now you can search it like:
var searchableTable = new XceedTableAdapter(doc.Tables[0]);
foreach (var col in dt.Columns)
{
ind = searchableTable.GetColumnIndex(col);
}
I have a checkedListBox1 and i want to convert all it's items to a DataGridView
i have the following code
string[] ar = new string[60];
for (int j = 0; j < checkedListBox1.Items.Count; j++)
{
ar[j] = checkedListBox1.Items[j].ToString();
}
dataGridView2.DataSource = ar;
but the dataGridView2 is filled with the length of the item instead of the item itself, can any one help?
These code blocks may give an idea (all is worked for me). CheckedListBox items returns a collection. It is coming from IList interface so if we use a List item as datasource for datagridview solves the problem. I used genericList as an additional class of Sample. When we use string array datagridview shows each items length. In here overried ToString returns original value.
class Sample
{
public string Value { get; set; }
public override string ToString()
{
return Value;
}
}
In form class:
private void button1_Click(object sender, EventArgs e)
{
CheckedListBox.ObjectCollection col = chk.Items;
List<Sample> list = new List<Sample>();
foreach (var item in col)
{
list.Add(new Sample { Value = item.ToString() });
}
dgw.DataSource = list;
}
This simple DataTable code appears to work...
DataTable dt = new DataTable();
dt.Columns.Add("Name", typeof(string));
for (int j = 0; j < checkedListBox1.Items.Count; j++) {
dt.Rows.Add(checkedListBox1.Items[j].ToString());
}
dataGridView1.DataSource = dt;
Because DataGridView looks for properties of containing objects. For string there is just one property - length. So, you need a wrapper for a string like this.
string[] ar = new string[60];
for (int j = 0; j < checkedListBox1.Items.Count; j++)
{
ar[j] = checkedListBox1.Items[j].ToString();
}
dataGridView1.DataSource = ar.Select(x => new { Value = x }).ToList();
I need to shuffle rows of DataTable as randomly accessing indexes would not work in my scenario. So I have dt1 having base data which I have to shuffle and dt is the DataTable having shuffled data. And my code is:
int j;
for (int i = 0; i < dt1.Rows.Count - 1; i++)
{
j = rnd.Next(0, dt1.Rows.Count - 1);
DataRow row = dt1.Rows[j];
dt.ImportRow(row);
}
Their is no syntax error but when I run my code where I further access dt I some of same rows get imported twice. What am I doing wrong here?
DataRow can only belong to a one DataTable, create a new Row with the values from existing DataRow.
dt.Rows.Add(row.ItemArray);
Or
dt.ImportRow(row);
Update:
Another approach to randomize any collection (From this Link).
public static class Extensions
{
private static Random random = new Random();
public static IEnumerable<T> OrderRandomly<T>(this IEnumerable<T> items)
{
List<T> randomly = new List<T>(items);
while (randomly.Count > 0)
{
Int32 index = random.Next(randomly.Count);
yield return randomly[index];
randomly.RemoveAt(index);
}
}
}
Now you can randomize any collection just by calling this extension function.
var dt = dt1.AsEnumerable()
.OrderRandomly()
.CopyToDataTable();
Check this Example
Here's an extension method I wrote for datatables. In a static DataTableExtensions Class
public static DataTable Shuffle(this DataTable table) {
int n = table.Rows.Count;
List<DataRow> shuffledRows = new List<DataRow>();
foreach (DataRow row in table.Rows) {
shuffledRows.Add(row);
}
while (n > 1) {
n--;
int k = Random.Range(0, n + 1);
DataRow value = shuffledRows[k];
shuffledRows[k] = shuffledRows[n];
shuffledRows[n] = value;
}
DataTable shuffledTable = table.Clone();
foreach (DataRow row in shuffledRows) {
shuffledTable.ImportRow(row);
}
return shuffledTable;
}
Probably not most efficient but it works.
use:
DataTable shuffledTable = otherDataTable.Shuffle();
here is my solution.
Just pass your table to the function and function will randomize the rows within the table.
public static void RandomizeTable(DataTable RPrl)
{
System.Security.Cryptography.RNGCryptoServiceProvider provider = new System.Security.Cryptography.RNGCryptoServiceProvider();
int n = RPrl.Rows.Count;
while (n > 1)
{
byte[] box = new byte[1];
do
{
provider.GetBytes(box);
}
while (!(box[0] < n * (System.Byte.MaxValue / n)));
int k = (box[0] % n);
n--;
object[] tmp = RPrl.Rows[k].ItemArray;
RPrl.Rows[k].ItemArray = RPrl.Rows[n].ItemArray;
RPrl.Rows[n].ItemArray = tmp;
}
}
I have a Dictionary type variable where I'm keeping "string" type key and "List " type values.
The problem is, in case of loop all the previous values are getting replaced by the last value.
Why this happens?
List<IWebElement> indicationsElement = ReturnIndicationList();
drugsDB = new List<string>();
for (int i = 0; i < indicationsElement.Count;i++ )
{
string key = indicationsElement[i].Text.ToString();
dt = ZittarPatt.getDrugsByIndication(ClientName, key);
drugsDB.Clear();
for (int k = 0; k < dt.Rows.Count; k++)
{
drugsDB.Add(dt.Rows[k].ItemArray[3].ToString().Trim());
}
drugsByindicationDictionary.Add(key, drugsDB);
}
You're adding the same reference every iteration instead of adding new instance of List<string>.
Every time you use .Clear it clears all the entries at drugsByindicationDictionary which are already the same entry.
Thus, only the last addition to drugsDB will be saved. (No .Clear is used at the end)
You should do the following code:
List<IWebElement> indicationsElement = ReturnIndicationList();
for (int i = 0; i < indicationsElement.Count;i++ )
{
string key = indicationsElement[i].Text.ToString();
dt = ZittarPatt.getDrugsByIndication(ClientName, key);
var drugsDB = new List<string>();
for (int k = 0; k < dt.Rows.Count; k++)
{
drugsDB.Add(dt.Rows[k].ItemArray[3].ToString().Trim());
}
drugsByindicationDictionary.Add(key, drugsDB);
}
Change drugsDB.Clear(); to drugsDB = new List<string>();
I am trying to having a new list added on every for loop iteration. I have the following code:
for (int i = 0; i < torni.Length; i++)
{
List<string> torni+i = // STUCK HER
}
Listnames should be like torni0, torni1, torni2 ......
Would really appreciate your assistance. Thanks!!
One way of doing this that would be slightly different would be to make a list of lists and then each index would be a discrete list.
You can't dynamically generate variable names in c#
like this:
tornis = new List<List<String>>()
for (int i = 0; i < torni.Length; i++)
{
tornis.append(new List<String>())
}
Alternatively as DanH Points out a dictionary of lists
tornis = new Dictionary<String,List<String>()
for (int i = 0; i < torni.Length; i++)
{
tornis.add("torni" + i, new List<String>())
}
This will give you a dictionary with the keys of the convention you want and a list of lists.
If you need each list only for the duration of a single loop iteration, then you don't need different list names:
for (int i = 0; i < torni.Length; i++)
{
List<string> temporaryList = new List<string>();
// use the list here
}