Three layer deep malleable strings
I'm trying to implement a three layer deep data structure. It is easy to do until you add the requirement of being able to move around the children and or fields, then it becomes a nightmare.
Parent(Index, ID) -> Children(Index) -> Fields(Index, string)
So for exa开发者_运维技巧mple, the data might look like this:
- Block1 ("Block1")
- Child1
- Field1 ("Hello")
- Field2 ("World")
- Child2
- Field1 ("One")
- Field2 ("Two")
- Field3 ("Three")
- Block2 ("Block2")
- Child1
Now I can implement this by making structs containing an ArrayList and String for both the Parent and Field, and just an Arraylist for Children, but when I need to for example invert Field1 and Field2 it becomes difficult and expensive.
This entire thing seems like it might be easy in a language like C++, since I could dump all the fields into a giant data block and then use pointers to reference where the fields are... Then if I want to switch fields, children, or parents, I just have to change the pointer, and it is cheap.
Has anyone seen this kind of data pattern in C# before? Is there a "standard" way to implement this?
Don't use structs, use classes. The operations are only expensive because using structs requires you to copy data around, whereas you could just be copying the object references. Your use of structs may be due to your experience with C++; in C# there are fewer occasions where you would want to use them.
When you instantiate your objects in C#, you "dump all the fields into a giant data block and then use pointers to reference where the fields are". That's what the new
operator does: it allocates objects on the heap and gives you pointers to them. There's no need to explicitly implement such a thing.
It is difficult to micro-manage memory explicitly in C# but if you stop trying to do so then I think you'll find your life getting much easier. If you really want to manage memory, go back to C++.
Why not simply organize that as an object hierarchy?
public class Block
{
public List<Child> Children { get; set; }
public string Name { get; set; }
}
public class Child
{
public List<Field> Fields { get; set; }
}
public class Field
{
public List<string> FieldNames { get; set; }
}
Then, you simply add a new reference to the lists, or you can simply prune references or sort the lists differently if you need to rearrange things. Am I missing something?
Swapping two references would actually be pretty cheap, and actually even if you wanted to remove an item from one child and add it to another it would still almost always be cheap enough.
using System.Collections.Generic;
public class Block : List<Child> {
public int ID { get; set; }
public Block(int id) {
this.ID = id;
}
}
public class Child : List<string> {
}
public class Test {
public static void Main() {
List<Block> blocks = new List<Block>() {
new Block(1) {
new Child() {
"Hello",
"World"
},
new Child() {
"One",
"Two",
"Three"
}
},
new Block(2) {
new Child()
}
};
string temp = blocks[0][0][0];
blocks[0][0][0] = blocks[0][0][1];
blocks[0][0][1] = temp;
}
}
Don't see any problem in managing of fields. Push them in List and at a time you deside to change a sequence, just swap objects in that list. If this is expensive from performance perspective, instead of having list you can use Dictionary with key like index of a field and value field itself and in case of need just swap ints.
精彩评论