Add an element/item to a multidimentional list - c#

I am trying to create a multidimensional list filled with an employee and their information.
Ex: "Jane Smith" "Manager" "75,000" "Dallas"
the code I have right now is giving me an out of range exception.
This bigROW[i].Add(ownName); and bigROW[i][j+1] = newElement; gives me errors.
//Begin making rows
for (int i = 0; i < fileRowCount; i++ )
{
string findOwners = "";
findOwners = file5Data.Rows[i][0].ToString();
if(DISTINCTOppOwners.Contains(findOwners))
{
//Find index of where owner is
int useIndex = 0;
useIndex = DISTINCTOppOwners.IndexOf(findOwners);
//Add their name to Multidimensional list
string ownName = DISTINCTOppOwners[useIndex].ToString();
//This line give me the ERROR
bigROW[i].Add(ownName);
for (int j = 0; j < fileColCount; j++)
{
Add Employee information to Multidimensional list
string newElement = file5Data.Rows[i][j].ToString();
if(ownName != newElement)
{
if(j ==0)
{
//Avoid adding their names to the list twice
bigROW[i][j+1] = newElement;
}
bigROW[i][j] = newElement;
}
}
}
}
I tried adding the info to a list called "sublist" then adding it to the BigRow(multidimensional list),but when I cleared the sublist to add a new row it deleted the values from the BigRow.

I tried adding the info to a list called "sublist" then adding it to the BigRow(multidimensional list),but when I cleared the sublist to add a new row it deleted the values from the BigRow.
When you add an object to a list what is stored is a reference, not the contents of the object. Instead of clearing sublist you should create a new List each time. Otherwise you have an outer list that contains multiple copies of the same list inside.
Refer to jdweng's answer above for an example of this. In his code the ToList call creates an new numbers list for each line, so that each row has its own List of numbers.

Here is a simple example
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication64
{
class Program
{
static void Main(string[] args)
{
string input =
"0,1,2,3,4,5,6,7,8,9\n" +
"10,11,12,13,14,15,16,17,18,19\n" +
"20,21,22,23,24,25,26,27,28,29\n" +
"30,31,32,33,34,35,36,37,38,39\n" +
"40,41,42,43,44,45,46,47,48,49\n";
List<List<int>> output = new List<List<int>>();
StringReader reader = new StringReader(input);
string inputline = "";
while ((inputline = reader.ReadLine()) != null)
{
List<int> numbers = inputline.Split(new char[] { ',' }).Select(x => int.Parse(x)).ToList();
output.Add(numbers);
}
}
}
}

Related

How can I split a string to store contents in two different arrays in c#?

The string I want to split is an array of strings.
the array contains strings like:
G1,Active
G2,Inactive
G3,Inactive
.
.
G24,Active
Now I want to store the G's in an array, and Active or Inactive in a different array. So far I have tried this which has successfully store all the G's part but I have lost the other part. I used Split fucntion but did not work so I have tried this.
int i = 0;
for(i = 0; i <= grids.Length; i++)
{
string temp = grids[i];
temp = temp.Replace(",", " ");
if (temp.Contains(' '))
{
int index = temp.IndexOf(' ');
grids[i] = temp.Substring(0, index);
}
//System.Console.WriteLine(temp);
}
Please help me how to achieve this goal. I am new to C#.
If I understand the problem correctly - we have an array of strings Eg:
arrayOfStrings[24] =
{
"G1,Active",
"G2,Inactive",
"G3,Active",
...
"G24,Active"
}
Now we want to split each item and store the g part in one array and the status into another.
Working with arrays the solution is to - traverse the arrayOfStrings.
Per each item in the arrayOfStrings we split it by ',' separator.
The Split operation will return another array of two elements the g part and the status - which will be stored respectively into distinct arrays (gArray and statusArray) for later retrieval. Those arrays will have a 1-to-1 relation.
Here is my implementation:
static string[] LoadArray()
{
return new string[]
{
"G1,Active",
"G2,Inactive",
"G3,Active",
"G4,Active",
"G5,Active",
"G6,Inactive",
"G7,Active",
"G8,Active",
"G9,Active",
"G10,Active",
"G11,Inactive",
"G12,Active",
"G13,Active",
"G14,Inactive",
"G15,Active",
"G16,Inactive",
"G17,Active",
"G18,Active",
"G19,Inactive",
"G20,Active",
"G21,Inactive",
"G22,Active",
"G23,Inactive",
"G24,Active"
};
}
static void Main(string[] args)
{
string[] myarrayOfStrings = LoadArray();
string[] gArray = new string[24];
string[] statusArray = new string[24];
int index = 0;
foreach (var item in myarrayOfStrings)
{
var arraySplit = item.Split(',');
gArray[index] = arraySplit[0];
statusArray[index] = arraySplit[1];
index++;
}
for (int i = 0; i < gArray.Length; i++)
{
Console.WriteLine("{0} has status : {1}", gArray[i] , statusArray[i]);
}
Console.ReadLine();
}
seems like you have a list of Gxx,Active my recomendation is first of all you split the string based on the space, which will give you the array previoulsy mentioned doing the next:
string text = "G1,Active G2,Inactive G3,Inactive G24,Active";
string[] splitedGItems = text.Split(" ");
So, now you have an array, and I strongly recommend you to use an object/Tuple/Dictionary depends of what suits you more in the entire scenario. for now i will use Dictionary as it seems to be key-value
Dictionary<string, string> GxListActiveInactive = new Dictionary<string, string>();
foreach(var singleGItems in splitedGItems)
{
string[] definition = singleGItems.Split(",");
GxListActiveInactive.Add(definition[0], definition[1]);
}
What im achiving in this code is create a collection which is key-value, now you have to search the G24 manually doing the next
string G24Value = GxListActiveInactive.FirstOrDefault(a => a.Key == "G24").Value;
just do it :
var splitedArray = YourStringArray.ToDictionary(x=>x.Split(',')[0],x=>x.Split(',')[1]);
var gArray = splitedArray.Keys;
var activeInactiveArray = splitedArray.Values;
I hope it will be useful
You can divide the string using Split; the first part should be the G's, while the second part will be "Active" or "Inactive".
int i;
string[] temp, activity = new string[grids.Length];
for(i = 0; i <= grids.Length; i++)
{
temp = grids[i].Split(',');
grids[i] = temp[0];
activity[i] = temp[1];
}

C# Populate An Array with Values in a Loop

I have a C# console application where an external text file is read. Each line of the file has values separated by spaces, such as:
1 -88 30.1
2 -89 30.1
So line one should be split into '1', '-88', and '30.1'.
What I need to do is to populate an array (or any other better object) so that it duplicate each line; the array should have 3 elements per row. I must be having a brain-lock to not figure it out today. Here's my code:
string line;
int[] intArray;
intArray = new int[3];
int i = 0;
//Read Input file
using (StreamReader file = new StreamReader("Score_4.dat"))
{
while ((line = file.ReadLine()) != null && line.Length > 10)
{
line.Trim();
string[] parts;
parts = line.Split(' ');
intArray[0][i] = parts[0];//error: cannot apply indexing
i++;
}
}
Down the road in my code, I intend to make some API calls to a server by constructing a Json object while looping through the array (or alternate object).
Any idea?
Thanks
If you only need the data to be transferred to JSON then you don't need to process the values of the data, just reformat it to JSON arrays.
As you don't know the number of lines in the input file, it is easier to use a List<>, whose capacity expands automatically, to hold the data rather than an array, whose size you would need to know in advance.
I took your sample data and repeated it a few times into a text file and used this program:
static void Main(string[] args)
{
string src = #"C:\temp\Score_4.dat";
List<string> dataFromFile = new List<string>();
using (var sr = new StreamReader(src))
{
while (!sr.EndOfStream)
{
string thisLine = sr.ReadLine();
string[] parts = thisLine.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 3)
{
string jsonArray = "[" + string.Join(",", parts) + "]";
dataFromFile.Add(jsonArray);
}
else
{
/* the line did not have three entries */
/* Maybe keep a count of the lines processed to give an error message to the user */
}
}
}
/* Do something with the data... */
int totalEntries = dataFromFile.Count();
int maxBatchSize = 50;
int nBatches = (int)Math.Ceiling((double)totalEntries / maxBatchSize);
for(int i=0;i<nBatches;i+=1)
{
string thisBatchJsonArray = "{\"myData\":[" + string.Join(",", dataFromFile.Skip(i * maxBatchSize).Take(maxBatchSize)) + "]}";
Console.WriteLine(thisBatchJsonArray);
}
Console.ReadLine();
}
to get this output:
{"myData":[[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1]]}
{"myData":[[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1]]}
It should be easy to adjust the format as required.
I would create a custom Item class and then populate a list, for easy access and sorting, with self contained items. something like:
public Class MyItem
{
public int first { get; set; }
public int second { get; set; }
public float third { get; set; }
public MyItem(int one, int two, float three)
{
this.first = one;
this.second = two;
this.third = three;
}
}
then you could do:
List<MyItem> mylist = new List<MyItem>();
and then in your loop:
using (StreamReader file = new StreamReader("Score_4.dat"))
{
while ((line = file.ReadLine()) != null && line.Length > 10)
{
line.Trim();
string[] parts;
parts = line.Split(' ');
MyItem item = new Item(Int32.Parse(parts[0]),Int32.Parse(parts[1]),Float.Parse(parts[2]));
mylist.Add(item);
i++;
}
}
As there are numbers like 30.1 so int is not suitable for this, and also it must not be a double[] but double[][]:
string[] lines = File.ReadAllLines("file.txt");
double[][] array = lines.Select(x => s.Split(' ').Select(a => double.Parse(a)).ToArray()).ToArray();
Issue is that int array is single dimensional.
My suggestion is that you can put a class with 3 properties and populate a list of class there. It's better to have class with same property names that you require to build JSON. So that you can easily serialize this class to JSON using some nugets like Newtonsoft and make api calls easily.
Your int array is a single dimensional array yet you're trying to index it like a multidemensional array. It should be something like this:
intArray[i] = parts[0]
(However you'll need to handle converting to int for parts that are fractional)
Alternatively, if you want to use a multidimensional array, you have to declare one.
int[][] intArray = new int[*whatever your expected number of records are*][3]
Arrays have a static size. Since you're reading from a file and may not know how many records there are until your file finishes reading, I recommend using something like a List of Tuples or a Dictionary depending on your needs.
A dictionary will allow you to have quick lookup of your records without iterating over them by using a key value pair, so if you wanted your records to match up with their line numbers, you could do something like this:
Dictionary<int, int[]> test = new Dictionary<int, int[]>();
int lineCount = 1;
while ((line = file.ReadLine()) != null && line.Length > 10)
{
int[] intArray = new int[3];
line.Trim();
string[] parts = line.Split(' ');
for (int i = 0; i < 3; i++)
{
intArray[i] = int.Parse(parts[i]);
}
test[lineCount] = intArray;
lineCount++;
}
This will let you access your values by line count like so:
test[3] = *third line of file*

Reading file to array

I am reading and counting the number of lines in a file, then initializing an array with the same number of spaces as the number of lines. The file is then read again and each line is assigned to that position of the array. For example, the first line would be stored in the index position of 0. I have the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace testProg
{
class program
{
static void main(){
Console.WriteLine("enter your filename for reading!");
fileName = Console.ReadLine();
using (StreamReader rs = new StreamReader(fileName))
{
string line2;
while ((line2 = rs.ReadLine()) != null)
{
arraysize = arraysize+1;//this goes through and gets the number of lines
}
}
Console.WriteLine(arraysize);
string[] unenc = new string[arraysize]; //this creates the array dynamically
int i = -1;//starts at position -1 then +1 so starts at 0
using (StreamReader fr = new StreamReader(fileName))
{
string linefinal;
while ((linefinal = fr.ReadLine()) != null)
{
Console.WriteLine(linefinal);//this will write the current line
unenc[i + 1] = linefinal;// this should store the string above in the current position
Console.WriteLine(unenc[i]);//this should output the same line it does not the index is just empty ? but it should be stored yet it is not
}
}
}
}
}
The problem is that you're not saving the incremented value of i anywhere.
You could modify you code like so:
while ((linefinal = fr.ReadLine()) != null)
{
Console.WriteLine(linefinal);
unenc[i + 1] = linefinal;
Console.WriteLine(unenc[i]);
i++;
}
So your query in comments is
would the array not update the value of i in the section where unenc[i+1]?
What i + 1 does is return the value of "i plus 1".
If you want to increment the value, you have two options:
Increment after returning value:
var oldValue = i++;
var newValue = i;
Increment before returning value:
var oldValue = i;
var newValue = ++i;
Code optimisation
You're having to read your file twice in order to get the number of lines so you can find out how big your array is. .NET provides a lovely class which will help you in this instance: List<>.
List<int> is a wrapper for int[] which manages the length of its internal array on the fly, which means while with an array you have to do this:
var array = int[3];
array[0] = 1;
array[1] = 2;
array[3] = 3:
with a List<int> you can simply do the following
var list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
With an array you'd have to copy to a larger array if you wanted to add another element, with list, this is all done for you internally.
Of course you can still access a list by var item = list[3];.
So utilising this, you can do away with the first read of the file and just keep adding to a list.
Instead of an array, consider using a List object. You can use the Add() method to continuously add items as you read them. Once complete, you can simply call the ToArray() method on the List object to get the array you need. You'll have all of the index values matching each line.
The line
unenc[i + 1] = linefinal;
isn't quite right. I belive you mean
unenc[i++] = linefinal;
Your line does not change the value of i as it goes through the loop.
Simple way is to use ArrayList. Please see the below code snippet
ArrayList lines = new ArrayList();
using (StreamReader rs = new StreamReader(#"C:\Users\vimal\Desktop\test.txt"))
{
string line = null;
while ((line = rs.ReadLine()) != null)
{
lines.Add(line);
}
}

how to remove duplicate data for group query in Linq

I'm trying to find a distinct list of filenames related to each bugid, and I used linq to group all filenames related to each bug id. I don't know how I can remove duplicate filenames related to each bugid,in file ouput I have multiple rows like this:
bugid filename1 filename2 filename3 filename4 .............
there are multiple rows with the same bugid and also there duplicate filenames for each bug id,
this is my code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
namespace finalgroupquery
{
class MainClass
{
public static void Main (string[] args)
{
List <bug> list2=new List <bug> ();
using(System.IO.StreamReader reader1= new System.IO.StreamReader( #"/home/output"))
using (System.IO.StreamWriter file = new System.IO.StreamWriter( #"/home/output1"))
{string line1;
while ((line1=reader1.ReadLine())!=null)
{ string[] items1=line1.Split('\t');
bug bg=new bug();
bg.bugid=items1[0];
for (int i=1; i<=items1.Length -1;i++)
{ bg.list1.Add(items1[i]);}
list2.Add(bg);
}
var bugquery= from c in list2 group c by c.bugid into x select
new Container { BugID = x.Key, Grouped = x };
foreach (Container con in bugquery)
{
StringBuilder files = new StringBuilder();
files.Append(con.BugID);
files.Append("\t");
foreach(var x in con.Grouped)
{
files.Append(string.Join("\t", x.list1.ToArray()));
}
file.WriteLine(files.ToString()); }
}
}
}
public class Container
{
public string BugID {get;set;}
public IGrouping<string, bug> Grouped {get;set;}
}
public class bug
{
public List<string> list1{get; set;}
public string bugid{get; set;}
public bug()
{
list1=new List<string>();
}
}
}
}
From your description it sounds like you want to do this:
List <bug> bugs = new List<bug>();
var lines = System.IO.File.ReadLines(#"/home/bugs");
foreach (var line in lines) {
string[] items = line.Split('\t');
bug bg=new bug();
bg.bugid = items[0];
bg.list1 = items.Skip(1).OrderBy(f => f).Distinct().ToList();
bugs.Add(bg);
}
This will produce a list of objects, where each object has a unique list of filenames.
Try to use this code :
var bugquery = from c in list2
group c by c.bugid into x
select new bug { bugid = x.Key, list1 = x.SelectMany(l => l.list1).Distinct().ToList() };
foreach (bug bug in bugquery)
{
StringBuilder files = new StringBuilder();
files.Append(bug.bugid);
files.Append("\t");
files.Append(string.Join("\t", bug.list1.ToArray()));
file.WriteLine(files.ToString());
}
Thanks to the combination of SelectMany and Distinct Linq operators, you can flatten the filename list and delete duplicates in a single line.
SelectMany (from msdn):
Projects each element of a sequence to an IEnumerable and flattens
the resulting sequences into one sequence.
Distinct (from msdn):
Returns distinct elements from a sequence.
It also means that your Container class is no longer needed as there's no need to iterate through the IGrouping<string, bug> collection anymore (here list1 contains all the bug related filenames without duplicates).
Edit
As you may have some blank lines and/or empty strings after reading and parsing your file, you could use this code to get rid of them :
using (System.IO.StreamReader reader1 = new System.IO.StreamReader(#"/home/sunshine40270/mine/projects/interaction2/fasil-data/common history/outputpure"))
{
string line1;
while ((line1 = reader1.ReadLine()) != null)
{
if (!string.IsNullOrWhiteSpace(line1))
{
string[] items1 = line1.Split(new [] { '\t' }, StringSplitOptions.RemoveEmptyEntries);
bug bg = new bug();
bg.bugid = items1[0];
for (int i = 1; i <= items1.Length - 1; i++)
{
bg.list1.Add(items1[i]);
}
list2.Add(bg);
}
}
}
You'll notice :
New lines stored in line1 are checked for emptyness as soon as they are retrieved from your stream (with !string.IsNullOrWhiteSpace(line1))
To omit empty substrings from the return value of the string.Split method, you can use the StringSplitOptions.RemoveEmptyEntries parameter.
Hope this helps.

How I get a Arraylist with not double values?

I want do get a Departmentlist from the Active Directory for this I use the Directoryentry and the DirectorySearcher class. I get the list of departments but how I can delete the double values in this list.
for example my list now:
it
it
it
vg
per
vg
...
And I want only one of this values in the list how this:
it
vg
per
...(other departments)
I want to use this list for a dropDownlist list.
my Code:
public static void GetAllDepartments(string domaincontroller)
{
ArrayList list = new ArrayList();
int Counter = 0;
string filter = "(&(objectClass=user)(objectCategory=user)(!userAccountControl:1.2.840.113556.1.4.803:=2)(sn=*)(|(telephoneNumber=*)(mail=*))(cn=*)(l=*))";
List<User> result = new List<User>();
DirectoryEntry Entry = new DirectoryEntry(domaincontroller);
DirectorySearcher Searcher = new DirectorySearcher(Entry, filter);
foreach (SearchResult usr in Searcher.FindAll())
{
result.Add(new User()
{
department = GetLdapProperty(usr, "Department")
});
Counter++;
}
for (int i = 0; i < Counter; i++)
{
list.Add(result[i].department);
}
}
How I can show only one value in the Arraylist?
First of all, I recommend that instead of using an ArrayList, use a Strongly-Typed list.
Then, use the Distinct() method to only get a list of unique values (no duplicates).
For instance:
List<String> list = new List();
....
for (int i = 0; i < Counter; i++)
{
list.Add(result[i].department.ToString());
}
var noDuplicates = list.Distinct();
Try Distinct() in System.Linq extensions :
list = list.Distinct();
You can also use the Exists clause to see if the element already exists in the list.
using System.Linq;
for (int i = 0; i < Counter; i++)
{
bool deptExists = list.Exists(ele => ele == result[i].department);
if(!deptExists){
list.Add(result[i].department);
}
}
Use the Enumerable.Distinct Method method.
Use a HashSet and only insert the non-duplicate values.
HashSet<string> list = new HashSet<string>();
...
for (int i = 0; i < Counter; i++)
{
string dep = result[i].department.ToString();
// true if dep was added, false if not. No exception at this point.
list.Add(dep);
}

Categories