I have a problem where I want to create a jagged array. But the size of this jagged array is variable.
Does this work the same way as filling an normal array like this?
int[] terms = new int[400];
for (int runs = 0; runs < 400; runs++)
{
terms[runs] = value;
}
The values I use are defined like this:
public static string[] nodeCassette0 = { "03", "08" };
public static string[] nodeCassette1 = { "04", "09" };
public static string[] nodeCassette2 = { "05", "10" };
public static string[] nodeCassette3 = { "06", "11" };
public static string[] nodeCassette4 = { "07", "12" };
Depending on the size required by the user a new variable nodeCassette needs to be filled according to the required size. The order in which the array is filled is always the same, it starts at 0 and ends at 4.
This should be like that but I don't know how to dynamically create it:
public string[][] nodeCassette =
{
nodeCassette0,
nodeCassette1,
nodeCassette2,
nodeCassette3,
nodeCassette4
};
Here's an example of how to create such a jagged array:
int[] sizes = new int[] { 3, 2, 1, 1, 3 };
int[][] jagged = new int[sizes.Length][];
for (int i = 0; i < sizes.Length; i++)
{
jagged[i] = new int[sizes[i]];
for (int j = 0; j < sizes[i]; j++)
{
jagged[i][j] = (i + 1) * (j + 1);
}
}
That produces:
It's no different with strings:
int[] sizes = new int[] { 3, 2, 1, 1, 3 };
string[][] jagged = new string[sizes.Length][];
for (int i = 0; i < sizes.Length; i++)
{
jagged[i] = new string[sizes[i]];
for (int j = 0; j < sizes[i]; j++)
{
jagged[i][j] = $"{i}_{j}";
}
}
We can use reflexion and Linq.
using System.Reflection;
using System.Linq;
Having this dedicated class to store the arrays by default, as well as initialize a complete list of possible elements, and offer a method to obtain a slice, i.e. a list made up of the first n-elements:
static class DefaultArrays
{
static public string[] NodeCassette0 = { "03", "08" };
static public string[] NodeCassette1 = { "04", "09" };
static public string[] NodeCassette2 = { "05", "10" };
static public string[] NodeCassette3 = { "06", "11" };
static public string[] NodeCassette4 = { "07", "12" };
static public List<string[]> All { get; private set; }
static public List<string[]> Take(int count)
{
return All.Take(count).ToList();
}
static public void Initialize()
{
All = typeof(DefaultArrays).GetFields()
.Where(field => field.FieldType == typeof(string[]))
.OrderBy(field => field.Name.Length)
.ThenBy(field => field.Name)
.Select(field => (string[])field.GetValue(null))
.ToList();
}
static DefaultArrays()
{
Initialize();
}
}
The Initialize method is created this way to possibly allow updating of the entire list in case the arrays are modified at runtime, otherwise the code can be placed directly in the constructor and all arrays marked readonly.
Here is the algorithm for All:
We get all fields of the static class by its type name.
We filter to select only those being of type array of string.
We order by the fields name string length.
Then by this name, thus we finally get for example 1, 2, 30, 40 from 40, 30, 2, 1.
We do a projection to get the reference of the value instead of the field name using it.
And we transform the Linq query into a List<string> object instance to return.
It uses a pseudo-natural numeric sort assuming all arrays are named:
"[same_same][number_without_trailing_left_0]"
Else we can use a custom comparer:
How do I sort strings alphabetically while accounting for value when a string is numeric?
sort string-numbers
Test
var slice = DefaultArrays.Take(3);
string msg = string.Join(Environment.NewLine, slice.Select(item => string.Join(", ", item)));
Console.WriteLine(msg);
Output
03, 08
04, 09
05, 10
Warning
The slice contains a list of references toward original arrays, thus any modification of a cell of an array in this list will be reflected in the matching array in the static class.
Else we need to copy the arrays with Array.Copy instead of using Linq.Take:
static public List<string[]> TakeCopy(int count)
{
var list = new List<string[]>();
foreach ( int index in Enumerable.Range(0, Math.Min(count, All.Count)))
{
int length = All[index].Length;
var array = new string[length];
Array.Copy(All[index], array, length);
list.Add(array);
}
return list;
}
I want to find range between closest value of this elements.
Delta value between elements. And it would be positive number because its modulus.
class Element {
double DeltaValue;
double ElementValue;
public Element(double n) {
ElementValue = n;
}
static void Main() {
list<Element> ListElements = new list<Elements>;
ListElements.Add(3);
ListElements.Add(10);
ListElements.Add(43);
ListElements.Add(100);
ListElements.Add(30);
ListElements.Add(140);
for(int i = 0; i < ListElements.Count; i++) {
ListElements[i].DeltaValue = //and problem is here
//example as for ListElements[2].DeltaValue will be 13; because 43-30=13;
}
//example as for ListElements[2].DeltaValue will be 13; because 43-30=13;
Just sort the array in increasing order and the smallest difference between the previous and the next element of the current element will solve your problem. Here for last element you can just look at the difference of its previous element.
Should be able to do it in one line with linq via the following:
public static int GetClosestVal(this int[] values, int place)
{
return values.OrderBy(v => Math.Abs(v - values[place])).ToArray()[1];
}
The following outputs 30
var testArray = new [] {3, 10, 43, 100, 30, 140};
Console.Write(testArray.GetClosestVal(2));
Basically speaking you sort by the absolute difference between each item and the chosen item, then grab the second item in the list since the first will always be the item itself (since n-n=0)
Thus the sorted list should be [43, 30, 20, 3, 100, 140]
I'm not sure, whether I understand your question right. If I have, then the following code snippet can help you:
class Program
{
static void Main(string[] args)
{
Elements ListElements = new Elements();
ListElements.ElementValue.Add(3);
ListElements.ElementValue.Add(10);
ListElements.ElementValue.Add(43);
ListElements.ElementValue.Add(100);
ListElements.ElementValue.Add(30);
ListElements.ElementValue.Add(140);
ListElements.CreateDeltaValues();
for (int i = 0; i < ListElements.DeltaValue.Count; i++)
{
Console.WriteLine("ListElement["+i+"]: " + ListElements.DeltaValue[i]);
//example as for ListElements[2].DeltaValue will be 13; because 43-30=13;
}
Console.ReadKey();
}
}
public class Elements
{
public List<double> DeltaValue = new List<double>();
public List<double> ElementValue = new List<double>();
public void CreateDeltaValues()
{
this.ElementValue.Sort();
for (int i = 1; i < this.ElementValue.Count; i++)
{
var deltaValue = this.ElementValue[i] - this.ElementValue[i-1];
this.DeltaValue.Add(deltaValue);
}
}
}
It's a console application, but this code should work also for other app models.
This code generates the following output:
I have an Array with Category Names, but now i Need to assign a few Counters to each Category.
Is there a way to expand my 1D-Array to a 2D-Array in C#?
Thanks for helping!
Edit:
PerformanceCounterCategory[] categories;
categories = PerformanceCounterCategory.GetCategories();
string[] categoryNames = new string[categories.Length];
string[] categoryNames_en = new string[categories.Length];
for (int objX = 0; objX < categories.Length; objX++)
{
categoryNames[objX] = categories[objX].CategoryName;
}
Array.Sort(categoryNames);
for (int objX = 0; objX < categories.Length; objX++)
{
Console.WriteLine("{0,4} - {1}", objX + 1, categoryNames[objX]);
}
I have the Array categoryNames with all the Names of the Categories, but in every Category there are a few Counters which i want to assign to their Category somehow...
Unfortunately you can't use Array.Copy since the source and destination array do not have the same dimensions.
Furthermore, you can't expand arrays in C#, since they are initialized with a fixed size.
What you can do is create a new array with a second dimonesion and copy the values over and set the second dimension to a default value.
void Main()
{
int[] sourceCollection = new [] {1,2,3,4,5,6,7} ;
var result = CopyArrayValues(sourceCollection, 2);
result.Dump();
}
//create a new 2d array
T[,] CopyArrayValues<T>(T[] DataSource, int SecondLength)
{
//Initialize the new array
var Target = new T[DataSource.Length, SecondLength];
//Copy values over
for (int i = 0; i < DataSource.Length; i++)
{
Target[i, 0] = DataSource[i];
}
return Target;
}
Output:
If it's ok for you to have array of arrays, you can do something along this pattern:
int[] sourceCollection = new[] { 1, 2, 3, 4, 5, 6, 7 };
int[][] arr = sourceCollection.Select(i => Enumerable.Range(i, 4).ToArray()).ToArray();
I want help with getting the subsets of an array in C#.
All other examples could not help me much.
I want to get all the subsets of a particular size of an array.
for example if input array is {1,2,3,4} and i want all subsets of size 3,
all the unique subsets {1,2,3},{1,2,4},{2,3,4},{1,3,4} must be returned.
I am new to C# and any kind of help is much appreciated.
Check this article. This is described in detail with examples in all sorts of programming languages. I don't feel the need to copy others solutions so I will leave this as a link for you to choose from the MANY examples which should help you
Algorithm to return all combinations of k elements from n
Sounds suspiciously like a homework assignment....
Since I presume the size is variable, you'll want to use recursion. Something like:
static void Main(string[] args)
{
int[] originalList = new int[] { 1, 2, 3, 4 };
Stack<int> currentList = new Stack<int>();
List<int[]> listOfSubsets = new List<int[]>();
BuildListOfSubsets(originalList, listOfSubsets, 3, 0, currentList);
}
private static void BuildListOfSubsets(int[] originalList, List<int[]> listOfSubsets, int sizeOfSubsetList, int currentLevel, Stack<int> currentList)
{
if (currentList.Count == sizeOfSubsetList)
{
int[] copy = new int[sizeOfSubsetList];
currentList.CopyTo(copy, 0);
listOfSubsets.Add(copy);
}
else
for (int ix = currentLevel; ix < originalList.Length; ix++)
{
currentList.Push(originalList[ix]);
BuildListOfSubsets(originalList, listOfSubsets, sizeOfSubsetList, ix + 1, currentList);
currentList.Pop();
}
}
The result will be in the listOfSubsets list. See if you can find an optimization to leave the for loop early.
If you are looking for a LINQ solution, try this:
int[] originalList = { 1,2,1 };
var srcl = originalList.ToList();
List<List<int>> ans = Enumerable.Range(0, srcl.Count).SelectMany(start => Enumerable.Range(1, srcl.Count - start).Select(count => srcl.GetRange(start, count))).ToList();
If you are looking for a simpler solution, without Recursion, then this will help:
(This is a common solution to print all the subsets, to print specific scenarios, like having only subsets with length as 3, use the innermost loop)
class Program
{
static void Main(string[] args)
{
int[] arr = { 1, 2, 3, 4, 5 };
int length = arr.Length;
for (int start = 0; start < length; start++)
{
for (int end = start; end < length; end++)
{
Console.Write("{");
// printing the subset, use this to add any condition,
// like create a array and match the length, or anything
for (int print = start; print <= end; print++)
{
Console.Write(arr[print]);
}
Console.WriteLine("}");
}
}
}
}
I have been stumped on this one for a while. I want to take a List and order the list such that the Products with the largest Price end up in the middle of the list. And I also want to do the opposite, i.e. make sure that the items with the largest price end up on the outer boundaries of the list.
Imagine a data structure like this.. 1,2,3,4,5,6,7,8,9,10
In the first scenario I need to get back 1,3,5,7,9,10,8,6,4,2
In the second scenario I need to get back 10,8,6,4,2,1,3,5,7,9
The list may have upwards of 250 items, the numbers will not be evenly distributed, and they will not be sequential, and I wanted to minimize copying. The numbers will be contained in Product objects, and not simple primitive integers.
Is there a simple solution that I am not seeing?
Any thoughts.
So for those of you wondering what I am up to, I am ordering items based on calculated font size. Here is the code that I went with...
The Implementation...
private void Reorder()
{
var tempList = new LinkedList<DisplayTag>();
bool even = true;
foreach (var tag in this) {
if (even)
tempList.AddLast(tag);
else
tempList.AddFirst(tag);
even = !even;
}
this.Clear();
this.AddRange(tempList);
}
The Test...
[TestCase(DisplayTagOrder.SmallestToLargest, Result=new[]{10,14,18,22,26,30})]
[TestCase(DisplayTagOrder.LargestToSmallest, Result=new[]{30,26,22,18,14,10})]
[TestCase(DisplayTagOrder.LargestInTheMiddle, Result = new[] { 10, 18, 26, 30, 22, 14 })]
[TestCase(DisplayTagOrder.LargestOnTheEnds, Result = new[] { 30, 22, 14, 10, 18, 26 })]
public int[] CalculateFontSize_Orders_Tags_Appropriately(DisplayTagOrder sortOrder)
{
list.CloudOrder = sortOrder;
list.CalculateFontSize();
var result = (from displayTag in list select displayTag.FontSize).ToArray();
return result;
}
The Usage...
public void CalculateFontSize()
{
GetMaximumRange();
GetMinimunRange();
CalculateDelta();
this.ForEach((displayTag) => CalculateFontSize(displayTag));
OrderByFontSize();
}
private void OrderByFontSize()
{
switch (CloudOrder) {
case DisplayTagOrder.SmallestToLargest:
this.Sort((arg1, arg2) => arg1.FontSize.CompareTo(arg2.FontSize));
break;
case DisplayTagOrder.LargestToSmallest:
this.Sort(new LargestFirstComparer());
break;
case DisplayTagOrder.LargestInTheMiddle:
this.Sort(new LargestFirstComparer());
Reorder();
break;
case DisplayTagOrder.LargestOnTheEnds:
this.Sort();
Reorder();
break;
}
}
The appropriate data structure is a LinkedList because it allows you to efficiently add to either end:
LinkedList<int> result = new LinkedList<int>();
int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Array.Sort(array);
bool odd = true;
foreach (var x in array)
{
if (odd)
result.AddLast(x);
else
result.AddFirst(x);
odd = !odd;
}
foreach (int item in result)
Console.Write("{0} ", item);
No extra copying steps, no reversing steps, ... just a small overhead per node for storage.
C# Iterator version
(Very simple code to satisfy all conditions.)
One function to rule them all! Doesn't use intermediate storage collection (see yield keyword). Orders the large numbers either to the middle, or to the sides depending on the argument. It's implemented as a C# iterator
// Pass forward sorted array for large middle numbers,
// or reverse sorted array for large side numbers.
//
public static IEnumerable<long> CurveOrder(long[] nums) {
if (nums == null || nums.Length == 0)
yield break; // Nothing to do.
// Move forward every two.
for (int i = 0; i < nums.Length; i+=2)
yield return nums[i];
// Move backward every other two. Note: Length%2 makes sure we're on the correct offset.
for (int i = nums.Length-1 - nums.Length%2; i >= 0; i-=2)
yield return nums[i];
}
Example Usage
For example with array long[] nums = { 1,2,3,4,5,6,7,8,9,10,11 };
Start with forward sort order, to bump high numbers into the middle.
Array.Sort(nums); //forward sort
// Array argument will be: { 1,2,3,4,5,6,7,8,9,10,11 };
long[] arrLargeMiddle = CurveOrder(nums).ToArray();
Produces: 1 3 5 7 9 11 10 8 6 4 2
Or, Start with reverse sort order, to push high numbers to sides.
Array.Reverse(nums); //reverse sort
// Array argument will be: { 11,10,9,8,7,6,5,4,3,2,1 };
long[] arrLargeSides = CurveOrder(nums).ToArray();
Produces: 11 9 7 5 3 1 2 4 6 8 10
Significant namespaces are:
using System;
using System.Collections.Generic;
using System.Linq;
Note: The iterator leaves the decision up to the caller about whether or not to use intermediate storage. The caller might simply be issuing a foreach loop over the results instead.
Extension Method Option
Optionally change the static method header to use the this modifier public static IEnumerable<long> CurveOrder(this long[] nums) { and put it inside a static class in your namespace;
Then call the order method directly on any long[ ] array instance like so:
Array.Reverse(nums); //reverse sort
// Array argument will be: { 11,10,9,8,7,6,5,4,3,2,1 };
long[] arrLargeSides = nums.CurveOrder().ToArray();
Just some (unneeded) syntactic sugar to mix things up a bit for fun. This can be applied to any answers to your question that take an array argument.
I might go for something like this
static T[] SortFromMiddleOut<T, U>(IList<T> list, Func<T, U> orderSelector, bool largestInside) where U : IComparable<U>
{
T[] sortedArray = new T[list.Count];
bool add = false;
int index = (list.Count / 2);
int iterations = 0;
IOrderedEnumerable<T> orderedList;
if (largestInside)
orderedList = list.OrderByDescending(orderSelector);
else
orderedList = list.OrderBy(orderSelector);
foreach (T item in orderedList)
{
sortedArray[index] = item;
if (add)
index += ++iterations;
else
index -= ++iterations;
add = !add;
}
return sortedArray;
}
Sample invocations:
int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int[] sortedArray = SortFromMiddleOut(array, i => i, false);
foreach (int item in sortedArray)
Console.Write("{0} ", item);
Console.Write("\n");
sortedArray = SortFromMiddleOut(array, i => i, true);
foreach (int item in sortedArray)
Console.Write("{0} ", item);
With it being generic, it could be a list of Foo and the order selector could be f => f.Name or whatever you want to throw at it.
The fastest (but not the clearest) solution is probably to simply calculate the new index for each element:
Array.Sort(array);
int length = array.Length;
int middle = length / 2;
int[] result2 = new int[length];
for (int i = 0; i < array.Length; i++)
{
result2[middle + (1 - 2 * (i % 2)) * ((i + 1) / 2)] = array[i];
}
Something like this?
public IEnumerable<int> SortToMiddle(IEnumerable<int> input)
{
var sorted = new List<int>(input);
sorted.Sort();
var firstHalf = new List<int>();
var secondHalf = new List<int>();
var sendToFirst = true;
foreach (var current in sorted)
{
if (sendToFirst)
{
firstHalf.Add(current);
}
else
{
secondHalf.Add(current);
}
sendToFirst = !sendToFirst;
}
//to get the highest values on the outside just reverse
//the first list instead of the second
secondHalf.Reverse();
return firstHalf.Concat(secondHalf);
}
For your specific (general) case (assuming unique keys):
public static IEnumerable<T> SortToMiddle<T, TU>(IEnumerable<T> input, Func<T, TU> getSortKey)
{
var sorted = new List<TU>(input.Select(getSortKey));
sorted.Sort();
var firstHalf = new List<TU>();
var secondHalf = new List<TU>();
var sendToFirst = true;
foreach (var current in sorted)
{
if (sendToFirst)
{
firstHalf.Add(current);
}
else
{
secondHalf.Add(current);
}
sendToFirst = !sendToFirst;
}
//to get the highest values on the outside just reverse
//the first list instead of the second
secondHalf.Reverse();
sorted = new List<TU>(firstHalf.Concat(secondHalf));
//This assumes the sort keys are unique - if not, the implementation
//needs to use a SortedList<TU, T>
return sorted.Select(s => input.First(t => s.Equals(getSortKey(t))));
}
And assuming non-unique keys:
public static IEnumerable<T> SortToMiddle<T, TU>(IEnumerable<T> input, Func<T, TU> getSortKey)
{
var sendToFirst = true;
var sorted = new SortedList<TU, T>(input.ToDictionary(getSortKey, t => t));
var firstHalf = new SortedList<TU, T>();
var secondHalf = new SortedList<TU, T>();
foreach (var current in sorted)
{
if (sendToFirst)
{
firstHalf.Add(current.Key, current.Value);
}
else
{
secondHalf.Add(current.Key, current.Value);
}
sendToFirst = !sendToFirst;
}
//to get the highest values on the outside just reverse
//the first list instead of the second
secondHalf.Reverse();
return(firstHalf.Concat(secondHalf)).Select(kvp => kvp.Value);
}
Simplest solution - order the list descending, create two new lists, into the first place every odd-indexed item, into the other every even indexed item. Reverse the first list then append the second to the first.
Okay, I'm not going to question your sanity here since I'm sure you wouldn't be asking the question if there weren't a good reason :-)
Here's how I'd approach it. Create a sorted list, then simply create another list by processing the keys in order, alternately inserting before and appending, something like:
sortedlist = list.sort (descending)
biginmiddle = new list()
state = append
foreach item in sortedlist:
if state == append:
biginmiddle.append (item)
state = prepend
else:
biginmiddle.insert (0, item)
state = append
This will give you a list where the big items are in the middle. Other items will fan out from the middle (in alternating directions) as needed:
1, 3, 5, 7, 9, 10, 8, 6, 4, 2
To get a list where the larger elements are at the ends, just replace the initial sort with an ascending one.
The sorted and final lists can just be pointers to the actual items (since you state they're not simple integers) - this will minimise both extra storage requirements and copying.
Maybe its not the best solution, but here's a nifty way...
Let Product[] parr be your array.
Disclaimer It's java, my C# is rusty.
Untested code, but you get the idea.
int plen = parr.length
int [] indices = new int[plen];
for(int i = 0; i < (plen/2); i ++)
indices[i] = 2*i + 1; // Line1
for(int i = (plen/2); i < plen; i++)
indices[i] = 2*(plen-i); // Line2
for(int i = 0; i < plen; i++)
{
if(i != indices[i])
swap(parr[i], parr[indices[i]]);
}
The second case, Something like this?
int plen = parr.length
int [] indices = new int[plen];
for(int i = 0; i <= (plen/2); i ++)
indices[i] = (plen^1) - 2*i;
for(int i = 0; i < (plen/2); i++)
indices[i+(plen/2)+1] = 2*i + 1;
for(int i = 0; i < plen; i++)
{
if(i != indices[i])
swap(parr[i], parr[indices[i]]);
}