Perserving Array from AnonymousType - c#

I looked online for some references but didn't have too much luck. Hopefully it's just some simple thing I'm overlooking, but in my code I'm looping through the participant list and storing the queried results into the array. As you can tell, my foreach statement will just add the last element of the array since the first one is replaced.
How can I just add the value to the next array index. So, if there are [2] in the array, how can I make sure that this.physEntityPhysicalLeftEntityIDs contains [2] instead of just always [1]? If I need to clarify, let me know.
if (leftParticipants.Length >= 0) // Check to see if LeftParticipants exists
{
for (int c = 0; c < leftParticipants.Length; c++)
{
var l_entityIDs =
from BioList in o_data.Descendants(bp + "physicalEntityParticipant")
where BioList.Attribute(rdf + "ID").Value == leftParticipants[c].TrimStart('#')
select new
{
o_entityIDs = BioList.Elements(bp + "PHYSICAL-ENTITY")
.Select(entityID => entityID.Attribute(rdf + "resource").Value).ToArray()
};
foreach (var entity in l_entityIDs)
{
this.physEntityPhysicalLeftEntityIDs = entity.o_entityIDs; // Set SmallMolecules from Left
}
}
}

If physEntityPhysicalLeftEntityIDs is an array, you'll need to initialize an index variable and increment it each time through the foreach loop:
int destIndex = 0;
foreach (var entity in l_entityIDs)
{
this.physEntityPhysicalLeftEntityIDs[destIndex] = entity.o_entityIDs; // Set SmallMolecules from Left
++destIndex;
}
That assumes that you've allocated enough space in the array. If there are more items than will fit in the array, you're going to get an index out of bounds error.
To make sure there's enough space in the array, you can allocate it before the loop above:
this.physEntityPhysicalLeftEntityIds = new int[l_entityIDs.Count()];
Replace int in that line with the proper type (you didn't say what type is being stored in the array).

Well if you want to treat it like an array/list, all you have to do is
l_enityIDs.ToList()
and then .Add(new {o_entityIDs = foo})
If you want to add it to the IEnumerable, that requires an extension method that returns everything in the source enumberable, and a yield statement adding on your next value.

Related

Searching a two dimensional object array in c#

I have declared a two-dimensional object array as
object[,] sectionOpenings = new object[20, 4];
The first column is populated with string types, whilst the remaining three columns are all integers.
I wish to do a quick search to find a row with a matching string in the first column and have tried this
var first = Array.Find(sectionOpenings, p => p == "homedepot");
I get the following error:
Error CS0411 The type arguments for method 'Array.Find(T[], Predicate)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Any suggestions?
You can alter your code a bit to get what you what:
var first = Array.Find(sectionOpenings, p => p[0] == "homedepot");
this will look in each array row, the first column p[0] == "homedepot"
edit:
my bad, I thought about jagged arrays
Well its not a one liner, but you can create a method like so:
public static int GetMatchingRow(object[,] myArr, string findMe)
{
for (int i = 0; i < myArr.GetLength(0); i++)
{
if (myArr[i, 0] is string && myArr[i, 0] as string == findMe)
return i;
}
return -1;
}
I would suggest changing to a dictionary to ensure type safety- like so:
var sectionOpenings = new Dictionary<string, List<int>>();
sectionOpenings.TryGetValue("homedepot", out var result);
However, if you are stuck using a 2D array, you'll likely have to do this in two steps. One, you'll have to find the matching column. Two, you'll have to retrieve the column. Something like this could work:
object[,] sectionOpenings = new object[20, 4];
var firstRowMatch = Enumerable
.Range(0, sectionOpenings.GetLength(0)) // Gets row indices
.Where(row => sectionOpenings[row, 0].ToString().Equals("homedepot"))
.First();
var result = Enumerable
.Range(0, sectionOpenings.GetLength(1)) // Gets column indices
.Select(column => sectionOpenings[firstRowMatch, column])
.ToArray();
With this example, you will likely have to add some type checks and null checks to make sure that this doesn't explode with a NullReferenceException.
This is adapted from returning a whole column from a 2D array and getting the number of columns/rows from a 2D array on stack overflow.
PS. This assumes you're using System.Linq

c# collections and re-numbering not working as expected

Hi i'm trying to setup simple test data.
I simply want to take a collection which is smallish and make it bigger by add itself multiple times.
After I;ve added them together i want to re-number the property LineNumber
so that there are no duplicates and that it goes in order. 1,2,3,4....
no matter what i try it doesn't seem to work and i cant see the mistake.
var sampleTemplateLine = dataContext.TemplateFileLines.ToList();
*//tired this doesnt work either*
//List<TemplateFileLine> lineRange = new List<TemplateFileLine>();
//lineRange.AddRange(sampleTemplateLine);
//lineRange.AddRange(sampleTemplateLine);
//lineRange.AddRange(sampleTemplateLine);
//lineRange.AddRange(sampleTemplateLine);
var allProducts = sampleTemplateLine
.Concat(sampleTemplateLine)
.Concat(sampleTemplateLine)
.Concat(sampleTemplateLine)
.ToList();
int i = 1;
foreach (var item in allProducts)
{
item.LineNumber = i;
i++;
}
this doesnt seem to work either
//re-number the line number
var total = allProducts.Count();
for (int i =0; i < total; i++)
{
allProducts[i].LineNumber = i+1;
}
PROBLEM: below RETURN 4 when i'm expecting 1
var itemthing = allProducts.Where(x => x.LineNumber == 17312).ToList();
You are adding the same objects multiple times. You wold have to add new objects or clone the ones you have.
The problem is they are pointing the same object. So if you change a property it changes all the pointed objects at the same
You can use Clone method if it exist, if not you can create your own Clone method like in this question.

RemoveAt() not working c#

Even after the RemoveAt() method, my list keeps being the same and I don't even get an error:
foreach (var row in queryCandidates.ToList())
{
try
{
xString = queryCandidates.ToList().ElementAt(i).District;
int.TryParse(xString, out xNumber);
temp = xNumber.Equals(districtNumber);
System.Diagnostics.Debug.Write(temp+ " ");
System.Diagnostics.Debug.Write(i+" ");
if (temp == false)
{
System.Diagnostics.Debug.WriteLine(" i is:"+i);
//not working even when it should
queryCandidates.ToList().RemoveAt(i);
}
}
catch { }
i++;
if (last == i)
{
System.Diagnostics.Debug.WriteLine("before ending loop: ");
return View(queryCandidates.ToList());
}
}
System.Diagnostics.Debug.WriteLine("after ending the loop: ");
return View(queryCandidates.ToList());
ToList() creates a new instance. From this instance you are removing the element. You are not removing the element from the original enumerable.
You should be doing something like this instead:
var candidates = queryCandidates.ToList();
var elementsToRemove = new List<int>();
foreach (var row in candidates)
{
// ...
xString = candidates[i].District;
// ...
if (temp == false)
{
// ...
elementsToRemove.Add(i);
}
}
for(int i = elementsToRemove.Count - 1; i >= 0; --i)
candidates.RemoveAt(elementsToRemove[i]);
return View(candidates);
Please note the use of elementsToRemove. You can't remove the items directly in the loop. This will throw an exception.
Additionally, please note that ToList copies all data. Every single time you call it. It should be obvious that this is not a good idea to do in a loop.
queryCandidates.ToList().RemoveAt(i);
ToList() creates a brand new list, which you then remove an element from, but that list is long gone.
Try:
var newList = queryCandidates.ToList();
for (int i=newList.Count-1; i>=0; i--){
///snip
newList.RemoveAt(i);
Note that I changed your foreach to for (in reverse) because you cannot modify a list while you are iterating over it with foreach.
The ToList() function creates a new List every time you call it. The object is removed from that list, not from the original list. So you should call ToList once before the foreach.
Once you've done that the removeAt() call will work and cause new issues because then you are trying to modify the list from within the foreach loop. So you'll need to rewrite your code in a way which takes the remove out of the loop as well.
Well I'm not exactly sure what Type queryCandidates is, but the reason you are not seeing an update is because you are removing element 'i' from the wrong object. Your ToList() function creates a new object of List type. If you want to keep the change you need to cache that list and use it where you use your original queryCandidates object.
queryCandidates isn't a list.
You're converting it to a list which creates a new instance from which you're removing the item but doesn't affect queryCandidates itself.
You can do:
var queryCandidates myCollection.ToList();
and then
queryCandidates.RemoveAt(i);
What works for me is to remove from the bottom up:
for (int i = list.Count - 1; i > 0; i--)
{
if (list[i][0] == " " || list[i][3] == "0")
list.RemoveAt(i);
}
It makes sense that some items are missed after decreasing the item count.

Convert GUID array to int array

I'm using linq query to create my collection based on it's id which is a guid.I've an item which can be associated to 1 or more products.What I need is to show all the productnames associated to that item and other datas like name,summary,date aswell.My issue here is when i try to use the variable i which is a guid in my array it throws error that Guid cannot be converted to int.I'm very sure that I've to convert my Guid array to int array but not sure how to implement it. below is my code.
foreach( Guid i in itemid)
{
var vals = from r in datacontext.ItemTable_s where r.itemID == i select r;
ItemTable_s[] tempdata = vals.ToArray<.ItemTable_s>();
Facet[] ftemp= new Facet[tempdata.Length];
ItemImage image = null;
string s1="";
for (int iv = 0; iv < tempdata.Length; iv++)
{
s1 += tempdata[i].productname + "\n";
}
ftemp[3] = new facet("Productname",facettype.text,s1);
collection.AddItem( tempdata[i].ItemName, null, null,
new ItemImage(new Uri(-tempdata[i].location))
);
}
In my above code tempdata[i] is where i get error msg saying guid cannot be converted to int implicitly.How do i fix this is there any other better approach?
Change your logic. Instead of using a foreach, use an int for statement. Then access the itemid's from the array. Something like this:Something like this:
for( int i=0; i<items.Count; i++)
{
...
var vals = from r in datacontext.ItemTable_s where r.itemID == itemid[i] select r;
...
s1 += tempdata[i].productname + "\n";
}
Didn't try the code, but I hope you'll get the idea...
(A GUID is 128 bits, so it cannot safely be converted into a 32-bit integer.)
A better option might be to use a Dictionary<Guid, ItemTable_s>. Then you can still use GUIDs to index it.
var tempdata = new Dictionary<Guid, ItemTable_s>;
foreach(var anItem in datacontext.ItemTable_s)
{
tempdata.Add(anItem.ItemID, anItem);
}
Then the line that's currently raising an exception (s1 += tempdata[i].productname + "\n";) should work as-is.
This will also make your itemid array unnecessary. Alternatively you could keep the two arrays you're using. Then you would have to change that line to:
s1 += tempdata[itemid.IndexOf(i)].productname + "\n";
It looks like that is what you were intending to do. But that will be much slower than using a dictionary. It means you'll be doing a sequential search of the itemid array every time you need to figure out where an entry is in tempdata.
A GUID looks like this
7c9e6679-7425-40de-944b-e07fc1f90ae7
As you can see there is not an Int Representation of that character. your Facet Constructor would need to take a GUID instead of an int.

c# Arrays - Index Out of Range Exception

I am getting indexoutofrangeexception (see ----> pointer for the line generating the error down below in the code). The program loops through the header and line item records in a dataset tables. The tables have a relationship. My sample data has 2 headers, each with 2 lines. The progam has two loops, the first one loops through the header records and the second one loops through the child records of the header.
Part of the program:
// ***** PO Header and Line
int ln;
ln = 0;
// Create an eConnect PO Header node object
taGLTransactionHeaderInsert jeh = new taGLTransactionHeaderInsert();
// Create an array for lineitems
taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[] lineitems = new taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[ln];
foreach (DataRow dtrHDR in ds.Tables["Header"].Rows)
{
Array.Clear(lineitems, 0, ln);
jeh.BACHNUMB = "Sheraz";
jeh.JRNENTRY = jenoint;
jeh.REFRENCE = dtrHDR["Reference"].ToString();
jeh.SOURCDOC = dtrHDR["AvantisJE"].ToString();
jeh.USERID = System.Environment.UserName;
jeh.TRXDATE = System.DateTime.Now.ToString();
ln = 0;
foreach (DataRow dtrLine in dtrHDR.GetChildRows("HdrLine"))
{
// Populate the elements of the taPoLIne_ItemsTaPOLine XML node
taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert jel = new taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert();
jel.BACHNUMB = jeh.BACHNUMB;
jel.JRNENTRY = jeh.JRNENTRY;
jel.ACTNUMST = dtrLine["GreatPlains"].ToString();
jel.DEBITAMT = Convert.ToDecimal(dtrLine["Debit"].ToString());
//Avantis Inv Trx Key
jel.ORDOCNUM = dtrLine["AvantisJE_Line"].ToString();
// Avantis GL Trx Type
jel.ORTRXDESC = dtrLine["transactiontypename"].ToString();
//Add POLine to an Array
lineitems[ln] = jel; ----------------> I get an error here!
ln = ln + 1;
Array.Resize(ref lineitems, ln + 1);
}
}
You are accessing an index that doesn't yet exist.
//Add POLine to an Array
lineitems[ln] = jel; ----------------> I get an error here!
ln = ln + 1;
Array.Resize(ref lineitems, ln + 1);
You need to change the order to :
//Add POLine to an Array
Array.Resize(ref lineitems, ln + 1);
lineitems[ln] = jel; ----------------> should be fixed, no error here!
ln = ln + 1;
EDIT: Now that the immediate problem is out of the way, on to a better implementation.
Arrays are of a fixed sized, resizing an array is an expensive operation (basically it entails creating a copy with a new size). typically you would use these after identifying a performance bottle neck. In most cases it would be much better to use a List.
I'd recommend changing this line:
// Create an array for lineitems
taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[] lineitems =
new taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[ln];
to:
var lineitems = new List<taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert>();
and then to add to it you simply do
lineitems.Add(jel);
to iterate over them would be:
for (var ln in lineitems) {
// whatever you want to do with a line.
}
to acccess a specific item by index would be:
lineitems.Item(i); // get the ith item in the list.
This is because you created an array with 0 elements and try to insert an element on position 0. This will not work. You can fix it by declaring the array with a size of 1 to begin with:
// Create an array for lineitems
taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[] lineitems = new taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[1];
However, resizing an array on the fly is not the idiomatic .NET way of doing this. You could use a List<T>, which takes care of resizing for you, and leaving you with cleaner code and possibly better performance.
It appears that you're trying to increase the size of the array by setting a value, like you might do in JavaScript. C# arrays are not like that. You need to create them at the size you want them to be when finished.
Alternately, you could use a List object, using the Add() method to put new content into the list.
lineitems is obviously not the same size as the row collection returned by dtrHDR.GetChildRows("HdrLine"). You are creating an array of zero elements and then trying to index into it. If you want it to match the size of dtrHDR.GetChildRows("HdrLine") then you need to call that first and initialize the array after you can get the count.
Instead of using an array why don't you use a List<T> and just push items onto it? No need to worry about IndexOutOfRange exceptions anymore.
You need to initialize the array before putting anything in to it. call the .resize first.
those lines are the problem
int ln;
ln = 0;
// Create an array for lineitems
taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[] lineitems = new taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[ln];
You create table of 0 elements.
You have an off-by-one error in your program:
int ln = 0
.
.
.
taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[] lineitems = new taGLTransactionLineInsert_ItemsTaGLTransactionLineInsert[ln];
.
.
.
lineitems[ln] = jel;
You are initializing an array of 0 elements, then trying to set the first element (element[0]) to a value.

Categories