|
Your issue is that you are trying to sort your lists as 4 different lists when they aren't. It's a single list of x items.
So just have:
class SomeObject
{
int Data[4];
}
List<SomeObject> lst;
When you sort, you would provide a custom compare function that'll look like:
int Compare(SomeObject x, SomeObject y)
{
compare x.Data[0] vs. y.Data[0] or whatever
}
and all "columns" will move together.
|
|
|
|
|
Option 2:
Wrap your lists with a class which applies the sort order where necessary:
public sealed class ListHelper<T> : IEnumerable<IList<T>>
{
private int _sortIndex = -1;
private IDictionary<int, int> _indexMap;
private IDictionary<int, int> _reverseIndexMap;
private readonly List<MappedList> _lists = new List<MappedList>();
public int SortIndex
{
get
{
return _sortIndex;
}
set
{
if (value < -1 || value >= _lists.Count)
{
throw new ArgumentOutOfRangeException();
}
if (-1 == value)
{
if (0 != _lists.Count)
{
int size = _lists[0].Count;
_indexMap = Enumerable.Range(0, size).ToDictionary(i => i);
_reverseIndexMap = _indexMap;
}
}
else
{
IList<T> sortKey = _lists[value].InnerList;
_indexMap = Enumerable.Range(0, sortKey.Count)
.OrderBy(i => sortKey[i])
.Select((key, v) => new { key, value = v })
.ToDictionary(p => p.key, p => p.value);
_reverseIndexMap = _indexMap.ToDictionary(p => p.Value, p => p.Key);
}
}
}
public int Count
{
get { return _lists.Count; }
}
public IList<T> this[int index]
{
get { return _lists[index]; }
}
public void Add(IList<T> listToAdd)
{
if (_indexMap == null)
{
_indexMap = Enumerable.Range(0, listToAdd.Count).ToDictionary(i => i);
_reverseIndexMap = _indexMap;
}
else if (_indexMap.Count != listToAdd.Count)
{
throw new ArgumentException("Invalid list size!", "list");
}
_lists.Add(new MappedList(listToAdd, this));
}
public IEnumerator<IList<T>> GetEnumerator()
{
return _lists.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
private sealed class MappedList : IList<T>
{
private readonly IList<T> _list;
private readonly ListHelper<T> _parent;
public MappedList(IList<T> list, ListHelper<T> parent)
{
_list = list;
_parent = parent;;
}
public IList<T> InnerList
{
get { return _list; }
}
public T this[int index]
{
get
{
int realIndex = _parent._reverseIndexMap[index];
return _list[realIndex];
}
set
{
int realIndex = _parent._reverseIndexMap[index];
_list[realIndex] = value;
}
}
public int Count
{
get { return _list.Count; }
}
public bool IsReadOnly
{
get { return _list.IsReadOnly; }
}
public IEnumerator<T> GetEnumerator()
{
for (int i = 0; i < _list.Count; i++)
{
int index = _parent._reverseIndexMap[i];
yield return _list[index];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public int IndexOf(T item)
{
int result = _list.IndexOf(item);
return -1 == result ? -1 : _parent._indexMap[result];
}
public void CopyTo(T[] array, int arrayIndex)
{
foreach (T item in this)
{
array[arrayIndex++] = item;
}
}
public bool Contains(T item)
{
return _list.Contains(item);
}
public void Add(T item)
{
throw new NotSupportedException();
}
public void Insert(int index, T item)
{
throw new NotSupportedException();
}
public bool Remove(T item)
{
throw new NotSupportedException();
}
public void RemoveAt(int index)
{
throw new NotSupportedException();
}
public void Clear()
{
throw new NotSupportedException();
}
}
}
...
var helper = new ListHelper<int>
{
new[] { 04, 09, 03, 06 },
new[] { 20, 50, 40, 30 },
new[] { 15, 45, 85, 65 },
new[] { 89, 39, 19, 99 },
};
helper.SortIndex = 0;
foreach (IList<T> list in helper)
{
for (int index = 0; index < list.Count; index++)
{
Console.WriteLine(list[index]);
}
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Perhaps have a List of Lists, where the first sub-list is the list of all the first values, etc.:
{
{ 09 , 20 , 15 , 89 }
{ 06 , 50 , 45 , 39 }
{ 04 , 40 , 85 , 19 }
{ 03 , 30 , 65 , 99 }
}
Then sort the outer list by the first (or whatever) element of each:
{
{ 03 , 30 , 65 , 99 }
{ 04 , 40 , 85 , 19 }
{ 06 , 50 , 45 , 39 }
{ 09 , 20 , 15 , 89 }
}
P.S. Could have made this a Friday Programming Challenge.
modified 21-Nov-12 15:14pm.
|
|
|
|
|
Make a wrapper class that you can use to preserve the order:
class OrderHelper<T> : IComparable<OrderHelper<T>> {
public T Item {get; private set;}
public int Order {get; private set;}
public OrderHelper(T item, int order) { this.Item = item; this.Order = order; }
public int CompareTo(OrderHelper<T> other) {
return Comparer<T>.Default.Compare(Item, other.Item);
}
}
Create a list of these from your primary sort list:
int index = 0;
List<OrderHelper<int>> orderedList = listOne.Select(i => new OrderHelper(i, index++)).ToList();
Sort that list, and then you can retrieve the index list:
orderedList.Sort();
List<int> indices = orderedList.Select(oi => oi.Order).ToList();
Finally you can order the other lists by that index set:
public static List<T> OrderBy(List<T> list, List<int> indices){
List<T> r = new List<T>(indices.Count);
for(int i = 0; i < r.Count; i++){
r[i] = list[indices[i]];
}
return r;
}
listTwo = OrderBy(listTwo, indicies);
listThree = OrderBy(listThree, indicies);
|
|
|
|
|
Hi,
I am learning OOP and trying to apply it to my C# WinForms applications.
So I have a Form with 2 textboxes. One to enter professor. Another to enter lecturer.
I have created an abstract 'Staff' class. Then I have a Professor class and a Lecturer class. Both inherit from Staff.
In Staff, I have declared an abstract property StaffName. So this must be implemented in other classes. Am I correct so far?
These classes are called on Button_Click event...
Professor professor = new Professor();
professor.StaffName = staffTextBox1.Text;
Lecturer lecturer = new Lecturer();
lecturer.StaffName = staffTextBox2.Text;
MessageBox.Show(string.Format("Analyst {0}\nSupervisor {1}", professor.StaffName, lecturer.StaffName), "Output", MessageBoxButtons.OK);
And my classes...
public abstract class Staff
{
protected string staffName;
public abstract string StaffName
{
get;
set;
}
}
public class Professor : Staff
{
public override string StaffName
{
get
{
return staffName;
}
set
{
staffName = value;
}
}
}
public class Lecturer : Staff
{
public override string StaffName
{
get
{
return staffName;
}
set
{
staffName = value;
}
}
}
Is this a correct OOP technique in WinForms or is there issues with my code design?
Thanks for your help!!
|
|
|
|
|
You should implement your StaffName property in your base (not abstract) class, as it will be used by all types. Any common properties or methods should be in the base class, and the child classes only need things that are unique to them. So you would have:
public class Staff
{
private string staffName;
public string StaffName
{
get
{
return staffName;
}
set
{
staffName = value;
}
}
}
public class Professor : Staff
{
}
public class Lecturer : Staff
{
}
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
Not sure if the OP noticed but I wanted to point this out. In Richard's response, he changed the access modifier for "string staffName" to "private" rather than "protected". Since the "StaffName" property is handled entirely by the base class, the derived types do not need to see the "staffName" member. "private" means that the object is only accessible to the class or struct defining it. "protected" would mean that the derived types could see the member as well.
EDIT:
Richard, I have a question about this now. Haha. What if the programmer decided to create a new class deriving from 'Staff' and the new class needed its own implementation of 'StaffName'? Would it be better to create a new 'private' field in the derived class? Or should 'private staffName' be changed to 'protected' in the base class? (I'm guessing create its own in the new class because none of the other derived types need it. But I wanted to clarify.)
djj55: Nice but may have a permission problem
Pete O'Hanlon: He has my permission to run it.
|
|
|
|
|
Matt U. wrote: In Richard's response, he changed the access modifier for "string staffName" to "private" rather than "protected". Exactly so, because the variable should only be accessible to the getter and setter in the base class; no other class needs to access it. In later versions of .NET you do not even need to define the variable as the compiler generates a hidden one automatically.
Matt U. wrote: What if the new class needed its own implementation of 'StaffName'? Why would it, it's only a name?
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
Perhaps that was a bad example. Or perhaps you see what I was getting at but it isn't really ever going to happen the way I was talking?
djj55: Nice but may have a permission problem
Pete O'Hanlon: He has my permission to run it.
|
|
|
|
|
Matt U. wrote: Perhaps that was a bad example. No, it was quite reasonable, but you need to understand the use and abuse of properties. They have a specific purpose and the important point is that the actual variable is always hidden from the outside world. If you need to access the variable from another class then you are breaking the encapsulation, and potentially, your program.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
That makes sense. Thanks for the clarification. I guess it's time I study OOP a bit more. Haha.
djj55: Nice but may have a permission problem
Pete O'Hanlon: He has my permission to run it.
|
|
|
|
|
Right. Perhaps a virtual property, but it doesn't sound like a good idea in this case. (I didn't even know properties could be virtual. Why?)
|
|
|
|
|
I don't see what that has to do with WinForms.
I agree with not making StaffName abstract, and using an auto-implemented property. And why name it StaffName rather than Name? And so far I see no reason for inheritance.
So, on the whole, I'd say, "no, it's not a good design (so far)", but that's just me.
Additionally, I'd suggest providing the name and such to the constructor -- an instance should be meaningful once it's instantiated, and a nameless Staff doesn't seem meaningful.
|
|
|
|
|
1 )Which part of your code do you add to your article
2) how much code should you add
3) how important are illustration
|
|
|
|
|
1) Anything required to build the demo -- you included a demo, right?
2) In the article with explanations? More is better.
3) Generally not very, but it depends on the subject. Please don't include screenshots of Visual Studio.
There is also an Article Writing forum here http://www.codeproject.com/Forums/1641/Article-Writing.aspx[^]
|
|
|
|
|
|
How Print Crystal Report in c# 2008 using Access Database ....
How set User Id, Password when Print Crystal Report????
|
|
|
|
|
Hi everybody,
I try to create a morse code sound with high speed. I referenced some project, and i used this project to reference. But when i used this code, it seems cannot hear the sound. Can anybody help me please?
Thank so much.
|
|
|
|
|
I really doubt that anyone here is going to download this project just to figure out what's wrong. If I were you, I would ask here[^] instead; they are more likely to know the answer.
|
|
|
|
|
|
No problem. I hope they can sort this issue out for you.
|
|
|
|
|
Hello,
I've been working on a program to renew Windows profiles on a remote location via Active Directory.
The program retrieves a user profile location(ProfilePath)
once the program verifies the email adres to be valid. The problem with the code provided below is that aside from the test e-mail account i used any other e-mail adres inputted returns the NullReferenceException.
my test account works perfectly and renames the profile to <profilename>.old. I can't think or see what i did wrong,
Any critisism or suggestions what i could try is welcome.
Thanks in advance.
Greetings,
Edit:
Found out the problem lies with loggin in with different credentials. I need to extend the right of the logged in over the entire application the loggin works but renaming a folder is not allowed on for the user running the application
private string GetProfilePath(string user)
{
DirectoryEntry dirEntry = CreateDirEntry();
DirectorySearcher dirSearcher = new DirectorySearcher();
dirSearcher.Filter = "mail=" + user;
dirSearcher.PropertiesToLoad.Add("profilePath");
SearchResult sResult = dirSearcher.FindOne();
if (sResult == null)
{
MessageBox.Show("Niks gevonden", "Niks gevonden", MessageBoxButtons.OK, MessageBoxIcon.Error);
SystemSounds.Beep.Play();
return null;
}
else
{
DirectoryEntry dirEntr = new DirectoryEntry(sResult.Path);
string profile = dirEntr.Properties["profilePath"].Value.ToString();
dirEntr.Close();
dirEntry.Close();
return profile;
}
}
modified 21-Nov-12 6:51am.
|
|
|
|
|
May I suggest you always write English, including comments.
I'm native Flemish speaking, but most on CP are not and if you're Belgian, you'd know that our French-speaking neighbors across the language border do not understand it either...
PS: Doesn't the Beep come AFTER you pressed OK on the Messagebox, in this case? Shouldn't it be before?
it's difficult to say what happens, but I suggest you add some logging and print out the different values, that might give you a clue.
|
|
|
|
|
doing so now.
and point taken about comments being in english.
My code is kinda messy at this point but the beep comes when the error box opens
Tested it beep comes when the error box opens but thanks for pointing it out
|
|
|
|
|
MacUseless wrote: and point taken about comments being in english.
You're welcome.
MacUseless wrote: Tested it beep comes when the error box opens but thanks for pointing it out
Against my expectations (messagebox blocks the thread, but if it works, it works )
|
|
|
|
|