Recursive function overwriting output list - c#

I was working on a class to find every combination of N lists. The combination algorithm seems to work flawlessly (when I step through it) but I am having trouble saving off my results. I want to store all the resulting arrays in another list to use later, but when I do the last array combination overwrites all the previous ones. Example input/outputs and my code are below. Does anyone have any ideas how I can fix this? (I've tried reference parameters and global lists with the same result).
/*
Input: A B C
X Y
Expected Output: A X
A Y
B X
B Y
C X
C Y
Actual Output: C Y
C Y
C Y
C Y
C Y
C Y
*/
public class Combination<T>{
private static void Combine(T[] res, int ix, List<List<T>> data, ref List<T[]> allCombos){
foreach (T v in data[ix]){
res[ix] = v;
if (ix >= data.Count - 1){
allCombos.Add(res);
}else{
Combine(res, ix + 1, data, ref allCombos);
}
}
}
public static List<T[]> Combine(List<List<T>> data){
List<T[]> allCombos = new List<T[]>();
Combine(new T[data.Count], 0, data, ref allCombos);
return allCombos;
}
}

The main problem here is that you only ever allocate a single T[] instance. Which you just add to your List<T[]> over and over.
Instead of this:
allCombos.Add(res);
You should try this:
allCombos.Add(res.ToArray());
That will create a new copy of the array each time as you add it to the list.

try this. I think this should work. I am not on terminal to test it.
public class Combination<T>
{
static T[] res;
private static void Combine(int ix, List<List<T>> data, ref List<T[]> allCombos)
{
foreach (T v in data[ix])
{
res[ix] = v;
if (ix >= data.Count - 1)
{
allCombos.Add(res);
}
else
{
Combine(res, ix + 1, data, ref allCombos);
}
}
}
public static List<T[]> Combine(List<List<T>> data)
{
List<T[]> allCombos = new List<T[]>();
res = new T[data.Count];
Combine(0, data, ref allCombos);
return allCombos;
}
}

The problem is that res argument is reused and overwritten in each iteration. Here is my solution for you.
using System;
using System.Linq;
using System.Collections.Generic;
....
private IEnumerable<T[]> Combine<T>(IEnumerable<T[]> data)
{
if (!data.Any())
yield break;
var head = data.First();
var tail = Combine(data.Skip(1));
foreach (var e in head)
{
var list = new T[] {e};
if (!tail.Any())
yield return list;
else
{
foreach (var t in tail)
{
yield return list.Concat(t).ToArray();
}
}
}
}

For the record, I had a similar issue, with a list of custom objects recently. What did it for me was basically creating a new object, using the object that used to get overwriten ("subTree") as the basis.
//Do this
TreeView newTree= new TreeView {
name = subTree.name,
children = subTree.children
};
actualTree.Add(newTree);
//Not this
actualTree.Add(subTree)
If I did not do that, I would have gotten the last "subTree" object everytime I tried to add a TreeView element to the "actualTree" List. The solution is to create a new object with the values that you need from other object whenever you have to add an element to your list, so that you are not always adding the same object.

Related

ref list isn't modified outside command class

I would like one class to modify the list fields of another class. I pass both list fields as references. The problem is, one list is modified in the end, and second is not. I don't understand why. I wanted to check my idea with a minimal working example, where everything works fine:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _20190424_ref_list_del
{
class Program
{
static void Main(string[] args)
{
ListManager testObj = new ListManager();
testObj.startJob();
}
}
class ListManager
{
private List<int> ListToExpand;
private List<int> ListToShorten;
public ListManager()
{
ListToExpand = new List<int>() { 1, 2, 3 };
ListToShorten = new List<int>() { 1, 2, 3 };
}
public void startJob()
{
EditList editObj = new EditList(ref ListToExpand, ref ListToShorten);
editObj.doJob();
System.Diagnostics.Debug.Print("List to expand:");
foreach (int x in ListToExpand)
{
System.Diagnostics.Debug.Print(x.ToString());
}
System.Diagnostics.Debug.Print("List to shorten:");
foreach (int x in ListToShorten)
{
System.Diagnostics.Debug.Print(x.ToString());
}
}
}
class EditList
{
private List<int> ListToExpand;
private List<int> ListToShorten;
public EditList(ref List<int> listToExpand, ref List<int> listToShorten)
{
ListToExpand = listToExpand;
ListToShorten = listToShorten;
}
public void doJob()
{
ListToExpand.Add(4);
ListToShorten.RemoveAt(0);
}
}
}
The main idea is:
Init two lists
Expand first and shorten another.
Check if there is an effect outside the working class, which modifies lists.
For this reason, I'm using ref. But the same approach in my real app fails. I have two lists too. One to be expanded, second to be shortened.
Let me explain what part of my code does: There is a list of samples from a Modbus device. Some of the samples require to be joined into bigger ones (because some of the values are so large that have values of int32 which need to be stored in two int16 registers).
I have a class with the Command design pattern which works as follows:
Create a Command object which takes:
(ref) input list of single samples
list of samples to be joined
(ref) list of samples joined to double ones
Build double samples
Remove single samples which have been joined
While testing, the list of double samples are filled, but the list of single ones isn't shortened. I don't understand why, because it looks like I'm using the same approach as in the minimal working example. Can you tell me what's wrong?
Test Case:
namespace put_samples_into_dbTests.Unit.Commands
{
[TestClass]
public class GetDoubleSamples
{
List<Sample> SingleSamples;
List<PatternSample32> SamplesPattern;
List<Sample32> ResultSamples;
int MaxSources = 2;
int MaxObjects = 3;
[TestInitialize]
public void TestInit()
{
SingleSamples = new List<Sample>();
SamplesPattern = new List<PatternSample32>();
ResultSamples = new List<Sample32>();
for (byte i = 1; i <= MaxSources; i++)
{
for (byte k = 2; k <= MaxObjects; k++)
{
SamplesPattern.Add(new PatternSample32(i, k, 1, 2));
}
}
}
[TestMethod]
public void BuildFrom1Set()
{
int howManySamples32 = MaxSources * (MaxObjects-1);
int howManySamples = MaxSources* ((1 + MaxObjects) * MaxObjects / 2) - howManySamples32 *2;
DateTime dateTime = DateTime.Now;
for (byte i = 1; i <= MaxSources; i++)
{
for (byte k = 1; k <= MaxObjects; k++)
{
for (byte l = 1; l <= k; l++)
{
SingleSamples.Add(new Sample(dateTime, i, k, l, 1, true));
}
}
}
Command command = new GetDoubleSamples(ref SingleSamples, SamplesPattern , ref ResultSamples );
command.Execute();
Assert.AreEqual(howManySamples, SingleSamples.Count); // [!]
Assert.AreEqual(howManySamples32, ResultSamples.Count);
}
Now, do take a look at my GetDoubleSamples command:
public class GetDoubleSamples : Command
{
private List<Sample> SingleSamples;
private List<PatternSample32> DoubleSamplesPattern;
private List<Sample32> ResultSamples;
private List<Sample> ProcessedSamples;
public GetDoubleSamples (ref List<Sample> singleSamples, List<PatternSamples32> doubleSamplesPattern, ref List<Sample32> resultSamples)
{
SingleSamples = singleSamples;
doubleSamplesPattern = doubleSamplesPattern;
ResultSamples = resultSamples;
ProcessedSamples = new List<Sample>();
}
public void Execute()
{
SortSamples();
foreach (List<Sample> samplesSet in GenerateSets())
{
ResultSamples.AddRange(BuildDoubles(samplesSet ));
}
DeleteProcessedSamples();
}
private void DeleteProcessedSamples()
{
SingleSamples = SingleSamples.Except(ProcessedSamples).ToList();
}
}
And the problem is, when I check for the amount of created double samples - it's okay. But the same (I suppose) kind of list of simple samples isn't reduced of processed samples. When I debug the code, I see that inside the class the mentioned list is modified. But once I get outside Execute methods and get outside Command class, I lose that modified list and get back to the original one. Just as if my list wasn't passed as a reference.
Do you have any idea what might be wrong?
Any suggestions, also about rearranging my test method, will be appreciated! :-)

algorithm for selecting N random elements from a List<T> in C# [duplicate]

This question already has answers here:
Randomize a List<T>
(28 answers)
Closed 6 years ago.
I need a quick algorithm to select 4 random elements from a generic list. For example, I'd like to get 4 random elements from a List and then based on some calculations if elements found not valid then it should again select next 4 random elements from the list.
You could do it like this
public static class Extensions
{
public static Dictionary<int, T> GetRandomElements<T>(this IList<T> list, int quantity)
{
var result = new Dictionary<int, T>();
if (list == null)
return result;
Random rnd = new Random(DateTime.Now.Millisecond);
for (int i = 0; i < quantity; i++)
{
int idx = rnd.Next(0, list.Count);
result.Add(idx, list[idx]);
}
return result;
}
}
Then use the extension method like this:
List<string> list = new List<string>() { "a", "b", "c", "d", "e", "f", "g", "h" };
Dictionary<int, string> randomElements = list.GetRandomElements(3);
foreach (KeyValuePair<int, string> elem in randomElements)
{
Console.WriteLine($"index in original list: {elem.Key} value: {elem.Value}");
}
something like that:
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
list.Add(5);
int n = 4;
var rand = new Random();
var randomObjects = new List<int>();
for (int i = 0; i<n; i++)
{
var index = rand.Next(list.Count);
randomObjects.Add(list[index]);
}
}
}
You can store indexes in some list to get non-repeated indexes:
List<T> GetRandomElements<T>(List<T> allElements, int randomCount = 4)
{
if (allElements.Count < randomCount)
{
return allElements;
}
List<int> indexes = new List<int>();
// use HashSet if performance is very critical and you need a lot of indexes
//HashSet<int> indexes = new HashSet<int>();
List<T> elements = new List<T>();
Random random = new Random();
while (indexes.Count < randomCount)
{
int index = random.Next(allElements.Count);
if (!indexes.Contains(index))
{
indexes.Add(index);
elements.Add(allElements[index]);
}
}
return elements;
}
Then you can do some calculation and call this method:
void Main(String[] args)
{
do
{
List<int> elements = GetRandomelements(yourElements);
//do some calculations
} while (some condition); // while result is not right
}
Suppose that the length of the List is N. Now suppose that you will put these 4 numbers in another List called out. Then you can loop through the List and the probability of the element you are on being chosen is
(4 - (out.Count)) / (N - currentIndex)
funcion (list)
(
loop i=0 i < 4
index = (int) length(list)*random(0 -> 1)
element[i] = list[index]
return element
)
while(check == false)
(
elements = funcion (list)
Do some calculation which returns check == false /true
)
This is the pseudo code, but i think you should of come up with this yourself.
Hope it helps:)
All the answers up to now have one fundamental flaw; you are asking for an algorithm that will generate a random combination of n elements and this combination, following some logic rules, will be valid or not. If its not, a new combination should be produced. Obviously, this new combination should be one that has never been produced before. All the proposed algorithms do not enforce this. If for example out of 1000000 possible combinations, only one is valid, you might waste a whole lot of resources until that particular unique combination is produced.
So, how to solve this? Well, the answer is simple, create all possible unique solutions, and then simply produce them in a random order. Caveat: I will suppose that the input stream has no repeating elements, if it does, then some combinations will not be unique.
First of all, lets write ourselves a handy immutable stack:
class ImmutableStack<T> : IEnumerable<T>
{
public static readonly ImmutableStack<T> Empty = new ImmutableStack<T>();
private readonly T head;
private readonly ImmutableStack<T> tail;
public int Count { get; }
private ImmutableStack()
{
Count = 0;
}
private ImmutableStack(T head, ImmutableStack<T> tail)
{
this.head = head;
this.tail = tail;
Count = tail.Count + 1;
}
public T Peek()
{
if (this == Empty)
throw new InvalidOperationException("Can not peek a empty stack.");
return head;
}
public ImmutableStack<T> Pop()
{
if (this == Empty)
throw new InvalidOperationException("Can not pop a empty stack.");
return tail;
}
public ImmutableStack<T> Push(T item) => new ImmutableStack<T>(item, this);
public IEnumerator<T> GetEnumerator()
{
var current = this;
while (current != Empty)
{
yield return current.head;
current = current.tail;
}
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
This will make our life easier while producing all combinations by recursion. Next, let's get the signature of our main method right:
public static IEnumerable<IEnumerable<T>> GetAllPossibleCombinationsInRandomOrder<T>(
IEnumerable<T> data, int combinationLength)
Ok, that looks about right. Now let's implement this thing:
var allCombinations = GetAllPossibleCombinations(data, combinationLength).ToArray();
var rnd = new Random();
var producedIndexes = new HashSet<int>();
while (producedIndexes.Count < allCombinations.Length)
{
while (true)
{
var index = rnd.Next(allCombinations.Length);
if (!producedIndexes.Contains(index))
{
producedIndexes.Add(index);
yield return allCombinations[index];
break;
}
}
}
Ok, all we are doing here is producing random indexees, checking we haven't produced it yet (we use a HashSet<int> for this), and returning the combination at that index.
Simple, now we only need to take care of GetAllPossibleCombinations(data, combinationLength).
Thats easy, we'll use recursion. Our bail out condition is when our current combination is the specified length. Another caveat: I'm omitting argument validation throughout the whole code, things like checking for null or if the specified length is not bigger than the input length, etc. should be taken care of.
Just for the fun, I'll be using some minor C#7 syntax here: nested functions.
public static IEnumerable<IEnumerable<T>> GetAllPossibleCombinations<T>(
IEnumerable<T> stream, int length)
{
return getAllCombinations(stream, ImmutableStack<T>.Empty);
IEnumerable<IEnumerable<T>> getAllCombinations<T>(IEnumerable<T> currentData, ImmutableStack<T> combination)
{
if (combination.Count == length)
yield return combination;
foreach (var d in currentData)
{
var newCombination = combination.Push(d);
foreach (var c in getAllCombinations(currentData.Except(new[] { d }), newCombination))
{
yield return c;
}
}
}
}
And there we go, now we can use this:
var data = "abc";
var random = GetAllPossibleCombinationsInRandomOrder(data, 2);
foreach (var r in random)
{
Console.WriteLine(string.Join("", r));
}
And sure enough, the output is:
bc
cb
ab
ac
ba
ca

Sort List which I use to fill ComboBox C#

Hello I've got code to fill ComboBox like this:
public ListBox fillComboBox(ListBox cb)
{
cb.Items.Clear();
foreach(string[] s in SO)
{
if (s[1].Split(',')[1].Equals("G5IDD"))
{
cb.Items.Add(s[1].Split(',')[3]);
}
}
cb.Sorted = true;
return cb;
}
In result I've got values sorted like this:
2.1
2.10
2.15
2.2
2.20
But I want it sorted like this
2.1
2.2
2.10
2.15
2.20
SO is ArrayList build by Arrays of string.
Can someone help me sort it way I want?
Thanks in advance
EDIT: Values can be like
4545_3434.2.1/1
4545_3434.2.1/2
4545_3434.2.2
4545_3434.2.2/1
Here is what I would suggest. No need for IComparer. This obviously assumes that the input will always be in the format of [int].[int].
public ListBox fillComboBox(ListBox cb)
{
cb.Items.Clear();
foreach(string[] s in SO.ToArray().OrderBy(s => Int32.Parse(s.ToString().Split('.')[0])).ThenBy(s => Int32.Parse(s.ToString().Split('.')[1])))
{
if (s[1].Split(',')[1].Equals("G5IDD"))
{
cb.Items.Add(s[1].Split(',')[3]);
}
}
return cb;
}
If you want the numbers treated as version, you can use the Version class.
public Version String2Version(string str)
{
string[] parts = str.Split('.');
return new Version(Convert.ToInt32(parts[0]), Convert.ToInt32(parts[1]));
}
public ListBox fillComboBox(ListBox cb)
{
cb.Items.Clear();
foreach(string[] s in SO)
{
if (s[1].Split(',')[1].Equals("G5IDD"))
{
cb.Items.Add( String2Version(s[1].Split(',')[3]));
}
}
cb.Sorted = true;
return cb;
}
You can use custom comparer(IComparer) in your code to achieve it,
I have provide an example.You have to change the logic of
public int Compare(object a, object b)
To achieve your specific requirement
class Program
{
private static ArrayList arl;
public static void Main(string[] args)
{
arl = new ArrayList();
arl.Add("2.1/1");
arl.Add("2.1/2");
arl.Add("2.2");
arl.Add("2.2/1");
arl.Sort(new IDDSort());
foreach (var value in arl)
{
Console.WriteLine(value);
}
Console.Read();
}
}
public class IDDSort : IComparer
{
public int Compare(object x, object y)
{
if (x == y) return 0;
var xparts = x.ToString().Replace("/","").Split('.');
var yparts = y.ToString().Replace("/", "").Split('.');
var length = new[] { xparts.Length, yparts.Length }.Max();
for (var i = 0; i < length; i++)
{
int xint;
int yint;
if (!Int32.TryParse(xparts.ElementAtOrDefault(i), out xint)) xint = 0;
if (!Int32.TryParse(yparts.ElementAtOrDefault(i), out yint)) yint = 0;
if (xint > yint) return 1;
if (yint > xint) return -1;
}
//they're equal value but not equal strings, eg 1 and 1.0
return 0;
}
}
This should work:
Array.Sort(SO, new AlphanumComparatorFast());
(if SO is the array with your version numbers)
Derive from ListBox and override Sort method implementing your own algorithm. For example the one suggested by Feroc.
Check link below:
http://msdn.microsoft.com/pl-pl/library/system.windows.forms.listbox.sort(v=vs.110).aspx
Hello I achieved my goal by coping part of array to list. (I needed only names on list not whole arrays). And used lambda expression for it.
list = list.OrderBy(x => Int32.Parse(x.Split('.')[2].Split('/')[0]))
.ThenBy(x =>
Int32.Parse(x.Split('.')[2].Split('/').Length > 1 ? x.Split('.')[2].Split('/')[1] : x.Split('.')[2].Split('/')[0])
).ToList();
So now I got it sorted like this:
0001.1
0001.2
0001.2/1
0001.2/2
0001.3
0001.3/1
etc.
Thanks everyone for help.

How do I compare items from a list to all others without repetition?

I have a collection of objects (lets call them MyItem) and each MyItem has a method called IsCompatibleWith which returns a boolean saying whether it's compatible with another MyItem.
public class MyItem
{
...
public bool IsCompatibleWith(MyItem other) { ... }
...
}
A.IsCompatibleWith(B) will always be the same as B.IsCompatibleWith(A). If for example I have a collection containing 4 of these, I am trying to find a LINQ query that will run the method on each distinct pair of items in the same collection. So if my collection contains A, B, C and D I wish to do the equivalent of:
A.IsCompatibleWith(B); // A & B
A.IsCompatibleWith(C); // A & C
A.IsCompatibleWith(D); // A & D
B.IsCompatibleWith(C); // B & C
B.IsCompatibleWith(D); // B & D
C.IsCompatibleWith(D); // C & D
The code initially used was:
var result = from item in myItems
from other in myItems
where item != other &&
item.IsCompatibleWith(other)
select item;
but of course this will still do both A & B and B & A (which is not required and not efficient). Also it's probably worth noting that in reality these lists will be a lot bigger than 4 items, hence the desire for an optimal solution.
Hopefully this makes sense... any ideas?
Edit:
One possible query -
MyItem[] items = myItems.ToArray();
bool compatible = (from item in items
from other in items
where
Array.IndexOf(items, item) < Array.IndexOf(items, other) &&
!item.IsCompatibleWith(other)
select item).FirstOrDefault() == null;
Edit2: In the end switched to using the custom solution from LukeH as it was more efficient for bigger lists.
public bool AreAllCompatible()
{
using (var e = myItems.GetEnumerator())
{
var buffer = new List<MyItem>();
while (e.MoveNext())
{
if (buffer.Any(item => !item.IsCompatibleWith(e.Current)))
return false;
buffer.Add(e.Current);
}
}
return true;
}
Edit...
Judging by the "final query" added to your question, you need a method to determine if all the items in the collection are compatible with each other. Here's how to do it reasonably efficiently:
bool compatible = myItems.AreAllItemsCompatible();
// ...
public static bool AreAllItemsCompatible(this IEnumerable<MyItem> source)
{
using (var e = source.GetEnumerator())
{
var buffer = new List<MyItem>();
while (e.MoveNext())
{
foreach (MyItem item in buffer)
{
if (!item.IsCompatibleWith(e.Current))
return false;
}
buffer.Add(e.Current);
}
}
return true;
}
Original Answer...
I don't think there's an efficient way to do this using only the built-in LINQ methods.
It's easy enough to build your own though. Here's an example of the sort of code you'll need. I'm not sure exactly what results you're trying to return so I'm just writing a message to the console for each compatible pair. It should be easy enough to change it to yield the results that you need.
using (var e = myItems.GetEnumerator())
{
var buffer = new List<MyItem>();
while (e.MoveNext())
{
foreach (MyItem item in buffer)
{
if (item.IsCompatibleWith(e.Current))
{
Console.WriteLine(item + " is compatible with " + e.Current);
}
}
buffer.Add(e.Current);
}
}
(Note that although this is reasonably efficient, it does not preserve the original ordering of the collection. Is that an issue in your situation?)
this should do it:
var result = from item in myItems
from other in myItems
where item != other &&
myItems.indexOf(item) < myItems.indexOf(other) &&
item.IsCompatibleWith(other)
select item;
But i dont know if it makes it faster, because in the query has to check the indices of the rows each row.
Edit:
if you have an index in myItem you should use that one instead of indexOf. And you can remove the "item != other" from the where clause, little bit redundant now
Here's an idea:
Implement IComparable so that your MyItem becomes sortable, then run this linq-query:
var result = from item in myItems
from other in myItems
where item.CompareTo(other) < 0 &&
item.IsCompatibleWith(other)
select item;
If your MyItem collection is small enough, you can storage the results of item.IsCompatibleWith(otherItem) in a boolean array:
var itemCount = myItems.Count();
var compatibilityTable = new bool[itemCount, itemCount];
var itemsToCompare = new List<MyItem>();
var i = 0;
var j = 0;
foreach (var item in myItems)
{
j = 0;
foreach (var other in itemsToCompare)
{
compatibilityTable[i,j] = item.IsCompatibleWith(other);
compatibilityTable[j,i] = compatibilityTable[i,j];
j++;
}
itemsToCompare.Add(item);
i++;
}
var result = myItems.Where((item, i) =>
{
var compatible = true;
var j = 0;
while (compatible && j < itemCount)
{
compatible = compatibilityTable[i,j];
}
j++;
return compatible;
}
So, we have
IEnumerable<MyItem> MyItems;
To get all the combinations we could use a function like this.
//returns all the k sized combinations from a list
public static IEnumerable<IEnumerable<T>> Combinations<T>(IEnumerable<T> list,
int k)
{
if (k == 0) return new[] {new T[0]};
return list.SelectMany((l, i) =>
Combinations(list.Skip(i + 1), k - 1).Select(c => (new[] {l}).Concat(c))
);
}
We can then apply this function to our problem like this.
var combinations = Combinations(MyItems, 2).Select(c => c.ToList<MyItem>());
var result = combinations.Where(c => c[0].IsCompatibleWith(c[1]))
This will perform IsCompatableWith on all the combinations without repetition.
You could of course perform the the checking inside the Combinations functions. For further work you could make the Combinations function into an extention that takes a delegate with a variable number of parameters for several lengths of k.
EDIT: As I suggested above, if you wrote these extension method
public static class Extenesions
{
IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> list, int k)
{
if (k == 0) return new[] { new T[0] };
return list.SelectMany((l, i) =>
list.Skip(i + 1).Combinations<T>(k - 1)
.Select(c => (new[] { l }).Concat(c)));
}
IEnumerable<Tuple<T, T>> Combinations<T> (this IEnumerable<T> list,
Func<T, T, bool> filter)
{
return list.Combinations(2).Where(c =>
filter(c.First(), c.Last())).Select(c =>
Tuple.Create<T, T>(c.First(), c.Last()));
}
}
Then in your code you could do the rather more elegant (IMO)
var compatibleTuples = myItems.Combinations(a, b) => a.IsCompatibleWith(b)))
then get at the compatible items with
foreach(var t in compatibleTuples)
{
t.Item1 // or T.item2
}

How do I convert an array of structs into an array of Point3D objects in C#?

I intend to form 3D mesh object.
The mesh object has an 3D point array of approx. 50.000 items.
Due to the number of 3D points, the array must be initialized on the heap.
The required code is, shortly, as follows:
class MyMesh
{
public MeshGeometry3D Mesh3D // Properties tanimlaniyor
{
get { return GetMesh3D(); }
}
public struct mystruct
{
public int m_i;
public int m_j;
public int m_k;
public mystruct(int i, int j, int k)
{
m_i = i;
m_j = j;
m_i = k;
}
}
private mystruct[] mypts =
{
new mystruct(20 , 7 , 7),
.
.
new mystruct(23 , 5 , 7)
};
}
Could you explain me how 3D Coordinates in mystruct above can be converted
into 3D coordinates of a System.Windows.Media.Media3D.Point3D structure.
Thanks in advance.
Öner YILMAZ
If you have an actual list of 50,000 mystruct objects, would it be better to just create them as Point3D structs in the first place?
Simply do a "Find & Replace" of:
new mystruct(
and replace it with
new Point3D(
Then, change:
private mystruct[] mypts =
to:
private Point3D[] mypts =
Are you looking for something like this...
List<Point3D> points = mypts.Select<mystruct, Point3D> (x =>
new Point3D(x.m_i, x.m_j, x.m_k))
.ToList();
Alternatively, you could expose an iterator that returned an IEnumerable like this...
public IEnumerable<Point3D> Points()
{
foreach(var point in mypts)
{
yield return new Point3D(point.m_i, point.m_j, point.m_k, );
}
}
[add validation/error handling code as appropriate]
If you need to retain your mystruct objects as well as enable Point3D functionality, you could use something like:
class MyMesh {
...
public Point3D[] ToPoint3D()
{
Point3D[] p3D = null; // or set it to an Empty Point3D array, if necessary
if (mpts.Length > 0)
{
p3D = new Point3D[mpts.Length]
for (int x = 0; x < mypts.Length; x++)
{
p3D[x].X = new Point3D(mypts[x].m_i;
p3D[x].Y = new Point3D(mypts[x].m_j;
p3D[x].Z = new Point3D(mypts[x].m_k;
}
}
return p3D;
}
...
}

Categories