List Sorting for treeview via linq - c#

I have A list
key ParentKey
1 Null
2 1
3 Null
4 Null
5 1
6 4
7 6
8 3
I want it sorted in
key ParentKey
1 Null
2 1
5 1
3 Null
8 3
4 Null
6 4
7 6
via linq how can this be done?
Any help is most wellcome

Assuming that the result should be:
key ParentKey
1 Null
2 1
5 1
3 Null
8 3
4 Null
6 4
7 6
I can say that you can't do anything if there isn't a logic that make the null values in that position into the list.
So using Linq you can order the list using the OrderBy() function:
list = list.OrderBy(x => x.ParentKey).ToList();
But using this function the result is the following:
key ParentKey
1 Null
3 Null
4 Null
2 1
5 1
8 3
6 4
7 6

if you have a list of
public class MyObject{
int Key {get;set;}
int ? ParentKey{get;set;}
}
then for sorting this list use :
var list = new List<MyObject>(){ new MyObject{ Key = 1 , ParentKey = null } , new MyObject{Key=2 , PatentKey = 1} /* and so on */};
var sortedList = list.OrderBy(o=>o.ParentKey , new MyComparer());
public class MyComparer : IComparer<MyObject>
{
public int Compare(MyObject o1, MyObject o2)
{
if (ol.HasValue && o2.HasValue)
{
if (ol.ParentKey.Value == o2.ParentKey.Value)
return 0;
return ol.ParentKey.Value > o2.ParentKey.Value ? 1 : -1;
}
else
return 0;
}
}
this will generate exact your expecting sequence

I believe what you want to achieve here is a DFS ordered print of a tree.
Linq can't help you with that (at least out of the box).
I'd suggest adapting a DFS implementation to your data structure. See Eric Lippert's suggestion.

Related

Jagged Array[][] find all selected elements in column

I have a jagged array:
int[][] loadData
a1
o1 | 3 1 5 4 3 3 1
o2 | 1 4 1 2 2 1 0
o3 | 4 4 5 4 4 3 1
o4 | 2 3 4 4 5 4 1
o5 | 3 3 5 2 5 5 1
o6 | 3 3 3 1 5 2 0
o7 | 2 5 3 5 1 2 1
o8 | 4 5 4 4 4 1 0 // this is my jagged array without o1 and a1 I use them for example
I want find all elements in column a1 who have number 3. I tried to mix the code but with no effect.
for example for 3 in column a1:
Dictionary<int, int?>[] matrix = new Dictionary<int, int?>[8];
matrix[0].Add(1, 3);
matrix[0].Add(5, 3);
matrix[0].Add(6, 3);
var x = Array.FindAll(loadData, a => Enumerable.Range(0, s)
.Select(j => loadData[j][0]));`
How to solve it?
The answer depends on what you mean by "find all."
If you want to find and count the number of rows, you can just
var count = array.Count( a => a[0] == 3 );
If you want to output the row numbers, it's a little trickier, since you have to pass the row number through before you apply the Where portion, or else the original row number will be lost.
var indexes = array.Select
(
(a, i) =>
new { RowNumber = i, Value = a[0]}
)
.Where( n => n.Value == 3 )
.Select( r => r.RowNumber )
You could also just flatten the array:
var flatList = array.SelectMany
(
(array, row) =>
array.Select
(
(element,column) =>
new { Row = row, Column = column, Value = element }
)
);
...and then query it like a flat table:
var indexes = flatList.Select
(
element => element.Column = 0 && element.Value == 3
)
.Select( a => a.Row );
I could be wrong but I think you may be looking for using linq is utilizing a .Where clause on a SelectMany statement. I had a question posted that was kind of similar although i was converting it into a string[][] array. https://stackoverflow.com/a/47784942/7813290

Creating all possible arrays without nested for loops [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I would like to generate all the possible numbers that have length n and each digit of my number has a value from the set {1,2,...,n-1}, as an array. In other words, I would like to list all the base n numbers with length n that do not include 0.
Right now, the only way I can think to do it is by nesting n for loops, and assigning myArray[i] with the (i+1)th loop, i.e.
int n;
int[] myArray = new int[n];
for (int i1 = 1; i1 < n; i1++)
myArray[0]=i1;
for (int i2 = 1; i2 < n; i2++)
myArray[1]=i2;
// and so on....
for (int in = 1; in < n; in++)
{
myArray[n]=in;
foreach (var item in myArray)
Console.Write(item.ToString());
Console.Write(Environment.NewLine);
}
and then printing each array at the innermost loop. The obvious issue is that for each n, I need to manually write n for loops.
From what I've read, recursion seems to be the best way to replace nested for loops, but I can't seem figure out how to make a general method for recursion either.
EDIT
For example, if n=3, I would like to write out 1 1 1, 1 1 2, 1 2 1, 1 2 2, 2 1 1, 2 1 2, 2 2 1, 2 2 2.
We are not limited to n<11. For example, if n=11, we would output
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 1 1 3
...
1 1 1 1 1 1 1 1 1 1 10
1 1 1 1 1 1 1 1 1 2 1
1 1 1 1 1 1 1 1 1 2 2
1 1 1 1 1 1 1 1 1 2 3
...
1 1 1 1 1 1 1 1 1 9 10
1 1 1 1 1 1 1 1 1 10 1
1 1 1 1 1 1 1 1 1 10 2
1 1 1 1 1 1 1 1 1 10 3
...
10 10 10 10 10 10 10 10 10 9 10
10 10 10 10 10 10 10 10 10 10 1
10 10 10 10 10 10 10 10 10 10 2
...
10 10 10 10 10 10 10 10 10 10 10
So, a digit of a number may be any value between and including 1 and 10. The array myArray is simply used to get one of these numbers, then we print it, and go on to the next number and repeat.
As always, when thinking in recursive solutions, try to solve the problem using immutable structures; everything is much simpler to understand.
So first of all, lets build ourselves a fast little immutable stack that will help us keep track of the number we are currently generating (while not worrying about what other numbers are being generated in the recursive call...remember, immutable data can't change!):
public class ImmutableStack<T>: IEnumerable<T>
{
public static readonly ImmutableStack<T> Empty = new ImmutableStack<T>();
private readonly T first;
private readonly ImmutableStack<T> rest;
public int Count { get; }
private ImmutableStack()
{
Count = 0;
}
private ImmutableStack(T first, ImmutableStack<T> rest)
{
Debug.Assert(rest != null);
this.first = first;
this.rest = rest;
Count = rest.Count + 1;
}
public IEnumerator<T> GetEnumerator()
{
var current = this;
while (current != Empty)
{
yield return current.first;
current = current.rest;
}
}
public T Peek()
{
if (this == Empty)
throw new InvalidOperationException("Can not peek an empty stack.");
return first;
}
public ImmutableStack<T> Pop()
{
if (this == Empty)
throw new InvalidOperationException("Can not pop an empty stack.");
return rest;
}
public ImmutableStack<T> Push(T item) => new ImmutableStack<T>(item, this);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
That's easy. Note how the stack reuses data. How many empty immutable structs will there be in our little program? Only one. And stacks containing the sequence 1->2->4? Yup, only one.
Now, we implement a recursive function that just keeps adding numbers to the stack until we reach our "bail out" condition. Which is? When the stack contains n elements. Easy peasy:
private static IEnumerable<int> generateNumbers(ImmutableStack<string> digits, IEnumerable<string> set, int length)
{
if (digits.Count == length)
{
yield return int.Parse(string.Concat(digits));
}
else
{
foreach (var digit in set)
{
var newDigits = digits.Push(digit);
foreach (var newNumber in generateNumbers(newDigits, set, length))
{
yield return newNumber;
}
}
}
}
Ok, and now we just need to tie it alltogether with our public method:
public static IEnumerable<int> GenerateNumbers(int length)
{
if (length < 1)
throw new ArgumentOutOfRangeException(nameof(length));
return generateNumbers(ImmutableStack<string>.Empty,
Enumerable.Range(1, length - 1).Select(d => d.ToString(CultureInfo.InvariantCulture)),
length);
}
And sure enough, if we call this thing:
var ns = GenerateNumbers(3);
Console.WriteLine(string.Join(Environment.NewLine,
ns.Select((n, index) => $"[{index + 1}]\t: {n}")));
We get the expected output:
[1] : 111
[2] : 211
[3] : 121
[4] : 221
[5] : 112
[6] : 212
[7] : 122
[8] : 222
Do note that the total amount of numbers generated of a specified length n is (n - 1) ^ n which means that for relatively small values of length you are going to get quite an amount of numbers generated; n = 10 generates 3 486 784 401...

Get the index of a node's parent, passing its index, in a balanced tree

Example:
I have the following example, that illustrate a championship schedule:
1 2 3 4 5 6 7 8
| | | |
9 10 11 12
| |
13 14
|
15
Rules:
The numbers represent the values of the nodes(matched). The value start from top to root, as the root is the final match of a championship.
The tree will be always balanced, and can have N top positions where N = {2,4,8,16,32,64,128,256...}
Problem:
I need to find a math function that will return the value of the node parent, passing its value. And this math function must be possible to be represented in C#.
GetNodeParent(9); // must return 13
GetNodeParent(10); // must return 13
GetNodeParent(4); // must return 10
GetNodeParent(15); // must return null
How should be the function?
In my opinion, the easiest way to handle this would be to store your tree the other way around. Normally a balanced tree can be represented in an array with the root at the first position and the leafs taking the last n/2 positions, looking like this :
1
|
2 3
| |
4 5 6 7
| | | |
8 9 10 11 12 13 14 15
which will look like this in memory :
1|2|3|4|5|6|7|8|9|10|11|12|13|14|15
Now an interesting property of this construction, is that the parent is always at Math.Floor(index/2) (so the children are at n*2 and n*2+1)
For example, the parent of 13 is 13/2 = 6.5 =floored= 6. It really simplifies the operations.
As said previously, all the leaf nodes are in the last n/2 positions. This is an other interesting fature; if you're looking for the first round matches, simply chop your array and take the Math.Ceiling(n/2) last items :
1|2|3|4|5|6|7|8|9|10|11|12|13|14|15
For the second round, remove the previous round and chop again at Math.Ceiling(n/2) :
1|2|3|4|5|6|7|
So knowing this, GetParent can look like the following :
public static int? GetParent(int childIndex)
{
int parentIndex = (int) Math.Floor((double)childIndex/2);
return parentIndex == 0 ? (int?)null : parentIndex;
}
or directly return (int)Math.Floor((double)index/2); if you don't need the null values.
This can be verified with this simple unit test made from your example values' position:
[TestMethod]
public void TestMethod1()
{
Assert.AreEqual(2, Stuff.GetParent(4));
Assert.AreEqual(2, Stuff.GetParent(5));
Assert.AreEqual(6, Stuff.GetParent(13));
Assert.AreEqual(null, Stuff.GetParent(1));
}
And also don't forget to work with indexes and not values, you can't directly apply the 9 and get 13 from your example, it's 4 and 2 now because that's their index in the tree with the root at the first position, which is constructed like. The example you provided would be constructed like that :
15|13|14|9|10|11|12|1|2|3|4|5|6|7|8
You can use IndexOf if you need to work by values. Since you're 1-based instead of 0-based, you'll also need to add 1 to every index. That would look like this :
[TestMethod]
public void TestMethod1()
{
List<int> values = new List<int>{15, 13, 14, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8};
Assert.AreEqual(values.IndexOf(13) + 1, Stuff.GetParent(values.IndexOf(9) + 1));
Assert.AreEqual(values.IndexOf(13) + 1, Stuff.GetParent(values.IndexOf(10) + 1));
Assert.AreEqual(values.IndexOf(10) + 1, Stuff.GetParent(values.IndexOf(4) + 1));
Assert.AreEqual(null, Stuff.GetParent(values.IndexOf(15)));
}
Option 1: Build a new tree that is the reverse, so you can use binary trees.
Option 2:
Call wil the list_name.Count(), I've used 15 for your case
GetNodeParent(9,15); // return 13
GetNodeParent(10,15);// return 13
GetNodeParent(4,15); // return 10
This works, but you'll have to check for the end cases (15 in your case):
int GetNodeParent(int aNodeValue, int aListSize) {
aNodeValue.Dump("Look for the parent of");
var depth = (int)(Math.Log(aListSize,2) ); // this rounds down
var level = Math.Pow(2,depth);
while (aNodeValue > level) {
depth--;
level += Math.Pow(2,depth);
}
var target = level+1; // this will be our accumulator
var search = level; // for our "binary search"
var search_width = Math.Pow(2,depth).Dump("width");
// This runs a "binary search", adding 1 to our result
// if we are on the right side.
while (search_width!=0){
if (aNodeValue > level)
target++;
search -= search_width / 2;
search_width /=2;
}
return (int)target;
}
as an after thought, add an if (aNodeValue == list_name.Count()) before you call the method, for the null, or change the signature to int? and do the check in the method so it'll return null
Have you tried this simple formula?
GetNodeParent(k) = (k + 1) div 2 + N
(if >=2N then null)
where div is integer division (7 div 2 = 3)

Paging through an IEnumerable

I have an IEnumerable object (IEnumerable<Class>) and I would like to retrieve a specified line from the object. So if I'm on page two I would like to select row two from the IEnumerable object and then pass it on to another class etc.
I'm a bit stuck at the moment, any ideas?
Look at the functions .Take() and .Skip(). I normally do something like this:
IEnumerable<object> GetPage(IEnumerable<object> input, int page, int pagesize)
{
return input.Skip(page*pagesize).Take(pagesize);
}
If I understand your requirements correctly, something like this paging mechanism should work:
int pageSize = 10;
int pageCount = 2;
iEnumerable.Skip(pageSize*pageCount).Take(pageSize);
This example shows 10 rows per page and a page number of 2. So, it will skip to page 2 and take the first row on that page.
Assuming that pages and rows start at 1, and there is a fixed number of rows per page (say 10), you need to transform the page number and the row to an index as follows:
Page 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 ...
Row 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 ...
↓
Index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ...
Code:
int page = 2;
int row = 2;
int rowsPerPage = 10;
IEnumerable<MyClass> source = ...
MyClass result = source.ElementAt((page - 1) * rowsPerPage + (row - 1));
So to get row 2 on page 2, you need to skip the first page (10 elements) and then take the second element (index 1 in that page).
I've implemented a dynamic solution in vb.net, i hope helpful:
<Runtime.CompilerServices.Extension()>
Public Function Paginate(Of T As {Class})(source As T, skip As Integer, take As Integer) As T
If source IsNot Nothing AndAlso TypeOf source Is IEnumerable Then
Dim chunk = (From c In DirectCast(source, IEnumerable)).Skip(skip).Take(take).ToList
If chunk.Count = 0 Then Return Nothing
Return AutoMapper.Mapper.Map(chunk, GetType(T), GetType(T))
End If
Return source
End Function

How to get the index of a record ordered by something in Linq?

Assume, I have student exam result set which is ordered by a point. I want to get the order index of a student in this result set. How can I get rid of that by using linq?
Assume the class like this;
class ExamResult
{
int StudentId;
int Point;
int ExamId;
}
ExamId StudentId Point
1 1 5,2
1 2 5,4
1 3 3
1 4 7,2
1 5 7,9
1 6 1
1 7 2,6
1 8 6
1 9 11
After I ordered the students by point. Student 2 has to be at index 5.
Are you using LINQ to Objects? If so, there's a Select overload which gives you the index as well as the value. (Ditto for Where and probably others too.) The Select overload therefore makes it easy to transform the original value into "original value + index" as an anonymous type.
Your question wasn't entirely clear - if this wasn't what you're after, perhaps you could give some sample code?

Categories

Resources