I have a getter that reads an existing array from another Property of that class and filters out elements with specific Properties.
The problem is, that after reading the Property it returns an array with the correct number of elements but all the containing elements are null.
During debugging I saw that the elements have been inserted correctly.
public Member[] Assigned_Users {
get {
Member[] _assigned_users = new Member[0];
//ERROR: foreach gets an array with the correct length, but all null elements
foreach (Member m in Nested_Users) {
if (m.Typ != Member.typ.User) continue;
Member[] _tmp = new Member[_assigned_users.Length + 1];
for (int r = 0; r <= _nested_members.Length - 1; r++) {
_tmp[r] = _assigned_users[r];
}
_tmp[_assigned_users.Length] = m;
_nested_members = _tmp;
}
foreach (Member m in Members) {
if (m.Typ != Member.typ.User) continue;
Member[] _tmp = new Member[_assigned_users.Length + 1];
for (int r = 0; r <= _nested_members.Length - 1; r++) {
_tmp[r] = _assigned_users[r];
}
_tmp[_assigned_users.Length] = m;
_nested_members = _tmp;
}
return _assigned_users;
}
}
public Member[] Nested_Users {
get {
Member[] _nested_users = new Member[0];
foreach (Member m in Nested_Members) {
if (m.Typ != Member.typ.User) continue;
Member[] _tmp = new Member[_nested_users.Length + 1];
for (int i = 0; i < _nested_users.Length - 1; i++) {
_tmp[i] = _nested_users[i];
}
_tmp[_nested_users.Length] = m;
_nested_users = _tmp;
}
//creates and returns a correct aray, acording to the debugger
return _nested_users;
}
}
Any Ideas how to fix this?
EDIT:
This code serves the following Purpose.
In the very ancient days of our company, a lot or LDAP groups existed. As many LDAP implementations don't allow to read all the users from a nested LDAP group, my company build their own User management back-end. This is one part of it.
If a group has a another group assigned (these infos are all stored in an SQL database) It should read the nested groups members and Assign them DIRECTLY to base group.
All of this is just done for services that authenticate against LDAP but don't know how to read users of a Nested group.
But even if List<Member> would be the better way to go, as suggested in the comments (and known by be), there should be no reason why the array is filled with null instead of Member objects. Or am I missing something here?
Related
Currently I have a class called Field:
public class Field
{
public int Id { get; set; }
}
var listOfListOfFields = new List<List<Field>>();
var listOfFields = new List<Field>(){ new Field {id = 1}}; // in reality, data comes here.
for (int i = 0; i <= 2; i++)
{
var copyFirstList = listOfFields.ToList(); // to avoid reference thing, I still get same value
for(int j =0; j < copyFirstList.Count; j++)
{
copyFirstList[j].Id = i;
}
listOfListOfFields.Add(copyFirstList);
}
The output in the listOfListOfFields contains 2 for all the lists in id. Please suggest.
Copying a list of references types gives you the same references to those reference types (nothing changed). For instance, if someone gave you a bucket of post-it-notes with phone numbers on them, and you tip them in to another bucket, you still have the same post-it-notes!
There are many ways to solve this problem. However, one way is to project using Select and recreating the objects
copyFirstList = listOfFields.Select(x => new Field() {Id = x.Id}).ToList():
I have a list with several columns. I need to create an ID for a block when my Column1="AA". If a previous block contains an ID, I should have ID+1.
I have something like this:
Column0|Column1|
23|AA
23|AA
23|AX
23|AX
23|AX
23|AA
23|AA
23|AX
23|AA
And I need something like this:
Column0|Column1|Column2
23|AA|1
23|AA|1
23|AX|
23|AX|
23|AX|
23|AA|2
23|AA|2
23|AX|
23|AA|3
In different words, I wanna create IDs (in seq.) to identify blocks of information that contain Column1=AA.
Side note: The order from the list is already the one that I needed.
So, should I use foreach or for loop? I am getting confused when I try to apply my ideas:
(_gDataID is my list; Columns Type will contain my AA or AX or ... ; SeqNumberOfTempCycle is the column that I wanna set with the "ID block" )
int lastseq = 0;
for (int i = 0; i < _gDataID.Count; i++)
{
if (_gDataID[i].Type.ToString() == "AA")
{
//Does the previous columns has a seq?
if (_gDataID[i-1].SeqNumberOfTempCycle.ToString() == null)
{
_gDataID[i].SeqNumberOfTempCycle = lastseq + 1;
lastseq = lastseq + 1;
}
else
{
_gDataID[i].SeqNumberOfTempCycle = lastseq;
}
}
}
As you may notice, my ideas are not working well. First, I cannot do this:
_gDataID[i].SeqNumberOfTempCycle = lastseq + 1;
And my for loop is not looping and setting up the field properly.
If I understand correctly, you need to update counter if there are gaps between the sequence of tokens. In that case, Use Dictionary to remember previously encountered token:
Dictionary<string, int> tokens = new Dictionary<string, int>();
int i = 0;
while(i < gDataID.Count)
{
string dataToken = gDataID[i].Type.ToString();
if(!tokens.ContainsKey(dataToken)
{
tokens.Add(dataToken, 0);
}
tokens[dataToken]++;
While(i < gDataID.Count && gDataID[i].Type.ToString() == dataToken)
{
gDataID[i].SeqNumberOfTempCycle = tokens[dataToken];
i++;
}
}
this is my very first post here on StackOverflow so please tell me if I did anything wrong, also english is not my native language, forgive me if there is any gramatical errors.
My question is how can I permutate the items of an array of type "Location", I need to get all possible permutations of waypoints given by the user to then calculate the best route based on time or distance. (I don't want to use the normal route calculation)
I've searched for algorithms but all of them when I put the array of type "Location[]" in the function's parameter I get the error that the object needs to be IEnumerable and I don't know how to convert to that if is even possible, I never worked with IEnumerable.
If it is of any help this is my code for calculating the route:
//Gets the waypoints from a listBox provided by the user, "mode" selects between best time and best distance
//backgroundworker so the UI dont freezes, and return the optimal waypoint order
public Location[] CalcularRota(Location[] waypoints, int mode, BackgroundWorker work, DoWorkEventArgs e)
{
//Declarations
string origem = "";
string destino = "";
Rota[] prop = new Rota[100]; //this index is the number of times the algorithm will be executed, more equals accuracy but much more time to complete
Rota bestDist = new Rota();
Rota bestTime = new Rota();
DirectionService serv = new DirectionService();
DirectionRequest reqs = new DirectionRequest();
DirectionResponse resp;
Random rnd = new Random();
Location[] rndWays;
int dist = 0;
int ti = 0;
bestDist.Distance = 1000000000; //put higher values for the first comparation to be true (end of code)
bestTime.Time = 1000000000;
if (waypoints != null)
{
reqs.Sensor = false;
reqs.Mode = TravelMode.driving;
for (int i = 0; i < prop.Length; i++) //initializes prop
prop[i] = new Rota();
for (int i = 0; i < prop.Length; i++)
{
rndWays = waypoints.OrderBy(x => rnd.Next()).ToArray(); //randomizes the order, I want to get all permutations and then test
//but I dont know how so I've been using randomized
dist = ti = 0;
origem = prop[0].ToString(); //save this particular waypoint's origin and destination
destino = prop[1].ToString();
reqs.Origin = origem;
reqs.Destination = destino;
if (waypoints.Length > 0)
reqs.Waypoints = rndWays;
resp = serv.GetResponse(reqs); //request the route with X order of waypoints to google
if (resp.Status == ServiceResponseStatus.Ok) //wait the response otherwise the program crashes
{
for (int j = 0; j < resp.Routes[0].Legs.Length; j++) //gets the distance and time of this particular order
{
ti += int.Parse(resp.Routes[0].Legs[j].Duration.Value);
dist += int.Parse(resp.Routes[0].Legs[j].Distance.Value);
}
}
prop[i].Origem = origem; //saves this waypoints order details for further comparison
prop[i].Destino = destino;
prop[i].Distance = dist;
prop[i].Time = ti;
prop[i].Order = rndWays;
work.ReportProgress(i); //report the progress
}
for (int i = 0; i < prop.Length; i++) //gets the best distance and time
{
if (bestDist.Distance > prop[i].Distance)
{
bestDist.Distance = prop[i].Distance;
bestDist.Time = prop[i].Time;
bestDist.Order = prop[i].Order;
bestDist.Origem = prop[i].Origem;
bestDist.Destino = prop[i].Destino;
}
if (bestTime.Time > prop[i].Time)
{
bestTime.Distance = prop[i].Distance;
bestTime.Time = prop[i].Time;
bestTime.Order = prop[i].Order;
bestTime.Origem = prop[i].Origem;
bestTime.Destino = prop[i].Destino;
}
}
if (bestDist.Order == bestTime.Order) //if the same waypoint order has the same time and distance
return bestDist.Order; // returns whatever bestDist.Order or bestTime.Order
else if (bestDist.Order != bestTime.Order) //if different returns corresponding to the mode selected
{
if (mode == 1) return bestDist.Order;
if (mode == 2) return bestTime.Order;
}
}
return null;
}
What I want is to permutate the waypoints given and test each permutation, I've been struggling with this for a time, if u guys could help me with any way possible would be great.
Ty.
EDIT.
I found this function here on StackOverflow:
public static bool NextPermutation<T>(T[] elements) where T : IComparable<T>
{
var count = elements.Length;
var done = true;
for (var i = count - 1; i > 0; i--)
{
var curr = elements[i];
// Check if the current element is less than the one before it
if (curr.CompareTo(elements[i - 1]) < 0)
{
continue;
}
// An element bigger than the one before it has been found,
// so this isn't the last lexicographic permutation.
done = false;
// Save the previous (bigger) element in a variable for more efficiency.
var prev = elements[i - 1];
// Have a variable to hold the index of the element to swap
// with the previous element (the to-swap element would be
// the smallest element that comes after the previous element
// and is bigger than the previous element), initializing it
// as the current index of the current item (curr).
var currIndex = i;
// Go through the array from the element after the current one to last
for (var j = i + 1; j < count; j++)
{
// Save into variable for more efficiency
var tmp = elements[j];
// Check if tmp suits the "next swap" conditions:
// Smallest, but bigger than the "prev" element
if (tmp.CompareTo(curr) < 0 && tmp.CompareTo(prev) > 0)
{
curr = tmp;
currIndex = j;
}
}
// Swap the "prev" with the new "curr" (the swap-with element)
elements[currIndex] = prev;
elements[i - 1] = curr;
// Reverse the order of the tail, in order to reset it's lexicographic order
for (var j = count - 1; j > i; j--, i++)
{
var tmp = elements[j];
elements[j] = elements[i];
elements[i] = tmp;
}
// Break since we have got the next permutation
// The reason to have all the logic inside the loop is
// to prevent the need of an extra variable indicating "i" when
// the next needed swap is found (moving "i" outside the loop is a
// bad practice, and isn't very readable, so I preferred not doing
// that as well).
break;
}
// Return whether this has been the last lexicographic permutation.
return done;
}
The usage is:
NextPermutation(array);
Doing this and putting my array (rndWays) as overload I get the following error:
The type 'Google.Maps.Location' cannot be used as type parameter 'T' in the generic type or method 'Form1.NextPermutation< T >(T[])'. There is no implicit reference conversion from 'Google.Maps.Location' to 'System.IComparable< Google.Maps.Location >'.
The problem is that Location does not implement the IComparable interface.
Change:
public static bool NextPermutation<T>(T[] elements) where T : IComparable<T>
to:
public static bool NextPermutation(Location[] elements)
And replace each CompareTo() with your own comparison function.
I have a implememtation where i need to loop through a collection of documents and based on certain condition merge the documents .
The merge condition is very simple, if present document's doctype is same as later document's doctype, then copy all the pages from the later doctype and append it to the pages of present document's and remove the later document from the collection.
Note : Both response.documents and response.documents[].pages are List<> collections.
I was trying this but was getting following exception Once I remove the document.
collection was modified enumeration may not execute
Here is the code:
int docindex = 0;
foreach( var document in response.documents)
{
string presentDoctype = string.Empty;
string laterDoctype = string.Empty;
presentDoctype = response.documents[docindex].doctype;
laterDoctype = response.documents[docindex + 1].doctype;
if (laterDoctype == presentDoctype)
{
response.documents[docindex].pages.AddRange(response.documents[docindex + 1].pages);
response.documents.RemoveAt(docindex + 1);
}
docindex = docindex + 1;
}
Ex:
reponse.documents[0].doctype = "BankStatement" //page count = 1
reponse.documents[1].doctype = "BankStatement" //page count = 2
reponse.documents[2].doctype = "BankStatement" //page count = 2
reponse.documents[3].doctype = "BankStatement" //page count = 1
reponse.documents[4].doctype = "BankStatement" //page count = 4
Expected result:
response.documents[0].doctype = "BankStatement" //page count = 10
Please suggest.Appreciate your help.
I would recommend you to look at LINQ GroupBy and Distinct to process your response.documents
Example (as I cannot use your class, I give example using my own defined class):
Suppose you have DummyClass
public class DummyClass {
public int DummyInt;
public string DummyString;
public double DummyDouble;
public DummyClass() {
}
public DummyClass(int dummyInt, string dummyString, double dummyDouble) {
DummyInt = dummyInt;
DummyString = dummyString;
DummyDouble = dummyDouble;
}
}
Then doing GroupBy as shown,
DummyClass dc1 = new DummyClass(1, "This dummy", 2.0);
DummyClass dc2 = new DummyClass(2, "That dummy", 2.0);
DummyClass dc3 = new DummyClass(1, "These dummies", 2.0);
DummyClass dc4 = new DummyClass(2, "Those dummies", 2.0);
DummyClass dc5 = new DummyClass(3, "The dummies", 2.0);
List<DummyClass> dummyList = new List<DummyClass>() { dc1, dc2, dc3, dc4, dc5 };
var groupedDummy = dummyList.GroupBy(x => x.DummyInt).ToList();
Will create three groups, marked by DummyInt
Then to process the group you could do
for (int i = 0; i < groupedDummy.Count; ++i){
foreach (DummyClass dummy in groupedDummy[i]) { //this will process the (i-1)-th group
//do something on this group
//groupedDummy[0] will consists of "this" and "these", [1] "that" and "those", while [2] "the"
//Try it out!
}
}
In your case, you should create group based on doctype.
Once you create groups based on your doctype, everything else would be pretty "natural" for you to continue.
Another LINQ method which you might be interested in would be Distinct. But I think for this case, GroupBy would be the primary method you would like to use.
Use only "for loop" instead of "foreach".
foreach will hold the collection and cannot be modified while looping thru it.
Here is an example using groupBy, hope this help.
//mock a collection
ICollection<string> collection1 = new List<string>();
for (int i = 0; i < 10; i++)
{
collection1.Add("BankStatement");
}
for (int i = 0; i < 5; i++)
{
collection1.Add("BankStatement2");
}
for (int i = 0; i < 4; i++)
{
collection1.Add("BankStatement3");
}
//merge and get count
var result = collection1.GroupBy(c => c).Select(c => new { name = c.First(), count = c.Count().ToString() }).ToList();
foreach (var item in result)
{
Console.WriteLine(item.name + ": " + item.count);
}
Just use AddRange()
response.documents[0].pages.AddRange(response.documents[1].pages);
it will merge all pages of document[1] with the document[0] into document[0]
I am correctly Appending my string with a For loop and iterator It not working it errors on the AppendLine Method of the string builder.
StringBuilder[] Certs;
//Just Display read outs here
var groups = from exp in main.Elements("Network")
where exp.Attribute("Nid").Value == IntializedNetworks[i].ToString()
select exp;
foreach (string exp in groups)
{
for (int x = 0; x < IntializedPostStat.Count(); x++)
{
Certs = new StringBuilder[IntializedPostStat.Count()];
int b = 0;
IntializedPostStat[x] = exp.ToString();
if (IntializedPostStat[i] != null)
{
Certs[x].Append("[Certificate] " + IntializedPostStat[x].ToString());
listBox1.Items.Add(Certs[x].ToString());
}
break;
}
}
You appear to be mixing your indexes, you are looping on x, but on this line you are indexing on i:
if (IntializedPostStat[i] != null)
{
Given that your indexes are out of sync it's not surprising that you are getting null reference exceptions.