If I have a list of 100 integers, how would I assign the values at index 20 to 50 to a different set of values in a list of length 31 without the use of loops? Coming from python this is very easy to do without looping but am unsure if it is possible to do in c#.
Using LINQ, which is "without using loops in my code", you could:
hundredInts.Take(19).Concat(thirtyoneInts).Concat(hundredInts.Skip(50));
(and if you want it back as a list or array etc, the relevant ToXXX call on the end of it)
Or perhaps:
hundredInts.Select((n, i) => (i < 20 || i > 50) ? n : thirtyOneInts[i-20])
Or built in stuff:
hundredInts.RemoveRange(20, 31).InsertRange(20, thirtyOneInts);
There's no trivial way to do so with Lists. However, this is easily done with arrays using Array.Copy:
var destIndex = 20;
Array.Copy(sourceArray, 0, destArray, destIndex, sourceArray.Length)
Well, if you can use loops under the hood, you can create an extension method, like
public static class MyExtensions{
public static void SetRange<T>(this List<T> source, IEnumerable<T> newValues, int startIndex){
var newValuesList = newValues.ToArray();
int numberOfElements = Math.Min(source.Count - startIndex, newValues.Count());
for(int i = 0; i < numberOfElements; i++){
source[i + startIndex] = newValuesList[i];
}
}
}
And use like the following:
var list = Enumerable.Range(0, 100).ToList();
var list2 = Enumerable.Range(1000, 31).ToList();
list.SetRange(list2, 20);
This will replace the values in list, starting at index 20, to the values of list2. You can also modify the extension method to add another parameter to estipulate the number of elements that you will take from list2, like the following:
public static void SetRange<T>(this List<T> source, IEnumerable<T> newValues, int startIndex, int numberOfElements){
var newValuesList = newValues.ToArray();
numberOfElements = Math.Min(numberOfElements, source.Count - startIndex);
numberOfElements = Math.Min(numberOfElements, newValues.Count());
for(int i = 0; i < numberOfElements; i++){
source[i + startIndex] = newValuesList[i];
}
}
You should probably also add a validation if startIndex and numberOfElements are greater than or equal to 0.
Related
I've tried changing my sort into a recursive function where the method calls itself. At least that's my understanding of recursion to forego for loops and the method calls itself to repeat the necessary iterations.
Below is my iterative verion:
for (int i = 0; i < Integers.Count; i++) //loops through all the numbers
{
min = i; //setting the current index number to be the minimum
for (int index = i + 1; index < Integers.Count; index++) //finds and checks pos of min value
{ //and switches it with last element using the swap method
if ((int) Integers[index] > (int) Integers[min]) {
min = index;
}
comparisons++;
}
if (i != min) //if statement for if swop is done
{
Swap(i, min, Integers, ref swops); //swap method called
}
//Swap method called
}
I've tried making it recursive. I read online that it was OK to still have for loops in a recursive funtion which I guess is not true. I just havent been able to develop a working sort. Am I going to need to split the method into 2 where one method traverses a list and the other does the sort?
Here's my selection sort recursive method attempt below:
static void DoSelectionSortRecursive(ArrayList Integers, int i, int swops, int comparisons) {
int min;
min = i;
for (int index = i + 1; index < Integers.Count; index++) //read online that the use of arraylists are deprecated, and i shoudlve rather used List<int> in order to remedy the code. is it necassary
{
if ((int) Integers[index] > (int) Integers[min]) {
min = index;
}
comparisons++;
}
if (i != min) {
Swap(i, min, Integers, ref swops);
}
DoSelectionSortRecursive(Integers, (i + 1), comparisons, swops); //DoSelectionSortRecursive method called
}
This is my imporved attempt including performance measures and everything. The original list of integers in the unsorted lists. 84,24,13,10,37.
and im getting 84,24,13,37,10. clearly not in a sorted descending order.
below is the improved code
static void DoSelectionSortRecursive(ArrayList Integers)
{
Stopwatch timer = new Stopwatch();
timer.Start();
int shifts = 0;
int swops = 0;
int comparisons = 0;
Sort(Integers, 1,ref swops,ref comparisons);
timer.Stop();
Console.WriteLine("Selection Sort Recursive: ");
Console.WriteLine(timer.ElapsedMilliseconds);
Console.WriteLine(swops);
Console.WriteLine(comparisons);
Console.WriteLine(shifts); //not needed in this sort
Console.WriteLine("-------------------------------------");
foreach (int i in Integers)
{
Console.WriteLine(i);
}
}
static void Sort(ArrayList Integers, int i, ref int swops, ref int comparisons)
{
int min = i;
int index = i + 1;
if (index < Integers.Count) //read online that the use of arraylists are deprecated, and i shoudlve rather used List<int> in order to remedy the code. is it necassary
{
if ((int)Integers[index] > (int)Integers[min])
{
min = index;
}
comparisons++;
index++;
}
if (i != min)
{
Swap(i, min, Integers, ref swops);
}
if (i < Integers.Count - 1)
{
Sort(Integers, (i + 1), ref comparisons, ref swops); //DoSelectionSortRecursive method called
}
}
static void Swap(int x, int y, ArrayList Integers, ref int swap) //swap method, swaps the position of 2 elements
{
swap++;
int temporary = (int)Integers[x]; //essentially will swap the min with the current position
Integers[x] = Integers[y];
Integers[y] = temporary;
}
There are no "rules" about recursion that say you cannot use loops in the recursive method body. The only rule in recursion is that the function has to call itself, which your second code snippet does, so DoSelectionSortRecursive is legitimately recursive.
For example, merge sort uses recursion for splitting the array and loops for merging the sorted subarrays. It'd be wrong to call it anything but a recursive function, and it'd be somewhat silly to implement the merging stage (an implementation detail of merge sort) recursively -- it'd be slower and harder to reason about, so loops are the natural choice.
On the other hand, the splitting part of merge sort makes sense to write recursively because it chops the problem space down by a logarithmic factor and has multiple branches. The repeated halving means it won't need to make more than a few or a dozen recursive calls on a typical array. These calls don't incur much overhead and fit well within the call stack.
On the other hand, the call stack can easily blow for linear recursive algorithms in languages without tail-call optimization like C# where each index in the linear structure requires a whole stack frame.
Rules prohibiting loops are concoted by educators who are trying to teach recursion by forcing you to use a specific approach in your solution. It's up to your instructor to determine whether one or both loops need to be converted to recursion for it to "count" as far as the course is concerned. (apologies if my assumptions about your educational arrangement are incorrect)
All that is to say that this requirement to write a nested-loop sort recursively is basically a misapplication of recursion for pedagogical purposes. In the "real world", you'd just write it iteratively and be done with it, as Google does in the V8 JavaScript engine, which uses insertion sort on small arrays. I suspect there are many other cases, but this is the one I'm most readily familiar with.
The point with using simple, nested loop sorts in performance-sensitive production code is that they're not recursive. These sorts' advantage is that they avoid allocating stack frames and incurring function call overhead to sort small arrays of a dozen numbers where the quadratic time complexity isn't a significant factor. When the array is mostly sorted, insertion sort in particular doesn't have to do much work and is mostly a linear walk over the array (sometimes a drawback in certain real-time applications that need predictable performance, in which case selection sort might be preferable -- see Wikipedia).
Regarding ArrayLists, the docs say: "We don't recommend that you use the ArrayList class for new development. Instead, we recommend that you use the generic List<T> class." So you can basically forget about ArrayList unless you're doing legacy code (Note: Java does use ArrayLists which are more akin to the C# List. std::list isn't an array in C++, so it can be confusing to keep all of this straight).
It's commendable that you've written your sort iteratively first, then translated to recursion on the outer loop only. It's good to start with what you know and get something working, then gradually transform it to meet the new requirements.
Zooming out a bit, we can isolate the role this inner loop plays when we pull it out as a function, then write and test it independent of the selection sort we hope to use it in. After the subroutine works on its own, then selection sort can use it as a black box and the overall design is verifiable and modular.
More specifically, the role of this inner loop is to find the minimum value beginning at an index: int IndexOfMin(List<int> lst, int i = 0). The contract is that it'll throw an ArgumentOutOfRangeException error if the precondition 0 <= i < lst.Count is violated.
I skipped the metrics variables for simplicity but added a random test harness that gives a pretty reasonable validation against the built-in sort.
using System;
using System.Collections.Generic;
using System.Linq;
class Sorter
{
private static void Swap(List<int> lst, int i, int j)
{
int temp = lst[i];
lst[i] = lst[j];
lst[j] = temp;
}
private static int IndexOfMin(List<int> lst, int i = 0)
{
if (i < 0 || i >= lst.Count)
{
throw new ArgumentOutOfRangeException();
}
else if (i == lst.Count - 1)
{
return i;
}
int bestIndex = IndexOfMin(lst, i + 1);
return lst[bestIndex] < lst[i] ? bestIndex : i;
}
public static void SelectionSort(List<int> lst, int i = 0)
{
if (i < lst.Count)
{
Swap(lst, i, IndexOfMin(lst, i));
SelectionSort(lst, i + 1);
}
}
public static void Main(string[] args)
{
var rand = new Random();
int tests = 1000;
int lstSize = 100;
int randMax = 1000;
for (int i = 0; i < tests; i++)
{
var lst = new List<int>();
for (int j = 0; j < lstSize; j++)
{
lst.Add(rand.Next(randMax));
}
var actual = new List<int>(lst);
SelectionSort(actual);
lst.Sort();
if (!lst.SequenceEqual(actual))
{
Console.WriteLine("FAIL:");
Console.WriteLine($"Expected => {String.Join(",", lst)}");
Console.WriteLine($"Actual => {String.Join(",", actual)}\n");
}
}
}
}
Here's a more generalized solution that uses generics and CompareTo so that you can sort any list of objects that implement the IComparable interface. This functionality is more akin to the built-in sort.
using System;
using System.Collections.Generic;
using System.Linq;
class Sorter
{
public static void Swap<T>(List<T> lst, int i, int j)
{
T temp = lst[i];
lst[i] = lst[j];
lst[j] = temp;
}
public static int IndexOfMin<T>(List<T> lst, int i = 0)
where T : IComparable<T>
{
if (i < 0 || i >= lst.Count)
{
throw new ArgumentOutOfRangeException();
}
else if (i == lst.Count - 1)
{
return i;
}
int bestIndex = IndexOfMin(lst, i + 1);
return lst[bestIndex].CompareTo(lst[i]) < 0 ? bestIndex : i;
}
public static void SelectionSort<T>(List<T> lst, int i = 0)
where T : IComparable<T>
{
if (i < lst.Count)
{
Swap(lst, i, IndexOfMin(lst, i));
SelectionSort(lst, i + 1);
}
}
public static void Main(string[] args)
{
// same as above
}
}
Since you asked how to smush both of the recursive functions into one, it's possible by keeping track of both i and j indices in the parameter list and adding a branch to figure out whether to deal with the inner or outer loop on a frame. For example:
public static void SelectionSort<T>(
List<T> lst,
int i = 0,
int j = 0,
int minJ = 0
) where T : IComparable<T>
{
if (i >= lst.Count)
{
return;
}
else if (j < lst.Count)
{
minJ = lst[minJ].CompareTo(lst[j]) < 0 ? minJ : j;
SelectionSort(lst, i, j + 1, minJ);
}
else
{
Swap(lst, i, minJ);
SelectionSort(lst, i + 1, i + 1, i + 1);
}
}
All of the code shown in this post is not suitable for production -- the point is to illustrate what not to do.
I am working with Arrays and conditionals statements, little lost right now and was hoping for some input.
So, I created two Arrays
int[] one = new int[] {
4160414, 6610574, 2864453, 9352227, -4750937, -3132620, 2208017,
-2226227, -8415856, -9834062, -3401569, 7581671, 8068562, 7520435,
-9277044, -7821114, -3095212, 966785, 6873349, -8441152, -7015683,
-6588326, -282013, 4051534, 9930123, -3093234 };
int[] two = new int[] {
1099626, 6083415, 8083888, -8210392, 2665304, -8710738, -8708241,
8859200, -1255323, 5604634, 2921294, -7260228, 7261646, 1137004,
5805162, 4883369, 8789460, 9769240, 319012, -7877588, -1573772,
5192333, 1185446, 1302131, 4217472, -3471445};
My next step what i was thinking is i am going to have to loop through each array
for (int i = 0; i < one.Length; i++)
{
int xValue = one[i];
for (int j = 0; j < two.Length; j++)
{
int yValue = two[j];
}
}
Now that i have the index of each Array i need to check wether the index of xValue is less than the index of yValue
if (xValue < yValue)
{
// dO SOMETHING HERE
}
if (yValue < xValue)
{
// Do Something HERE
}
Where i am getting confused at, is with C# from my understanding you can not push new values into an Array, it needs to be a new instance of the array and copy?
So i tried doing
if (xValue < yValue)
{
Array.Copy(one, x, 13);
}
if (yValue < xValue)
{
Array.Copy(two, x, 13)
}
Both Arrays have 26 values, so a new array of 13 would need to be created to insert the checked value, but Array.Copy seems to not be working getting an array out of bounds check lower bounds.
I'm just confused on checking the values of both arrays at their index, then grabbing the smallest value of the checked values then taking that small value and inserting it into a new array, then use a foreach-loop to iterate over it and print the values to the console. FacePalm
You can use LINQ's Zip to achieve this:
int[] smallest = one.Zip(two, (o, t) => Math.Min(o,t)).ToArray();
Essentially, Zip will provide both items to the lambda expression, allowing you to combine them how you see fit. In this case, we just choose the minimum and return it.
Try it online
Basically, you need to define the size of the new array when you declare it. Make it the same size as one. Then add the smallest item from one or two on each iteration by comparing the items in each array at index i.
int[] smallest = new int[one.Length];
for (int i = 0; i < one.Length; i++)
{
if (one[i] < two[i])
{
smallest[i] = one[i];
}
else
{
smallest[i] = two[i];
}
}
This question already has answers here:
How to Sort a List<T> by a property in the object
(23 answers)
Closed 6 years ago.
I've written the the selection sort method beneath. I would like to retain the code in general as it's a school exercise, but I understand that there are more correct ways to do it, as with Linq.
It works well besides that it only sorts the property PersonalNumber. I can see where the error is the following:
temp = list[i].PersonalNumber;
list[i].PersonalNumber = list[posMin].PersonalNumber;
list[posMin].PersonalNumber = temp;
Is there any way to sort all of the properties contained for each index in the list? Or do I have to write the above code for each property? There are three properties in total.
Full method:
public static void SelectionSort(List<Person> list) {
// With this method the Person list is sorted in ascending order.
//posMin is short for position of min
int posMin, temp;
for (int i = 0; i < list.Count - 1; i++) {
posMin = i;//Set posMin to the current index of array
for (int j = i + 1; j < list.Count; j++) {
if (list[j].PersonalNumber < list[posMin].PersonalNumber) {
//posMin will keep track of the index that min is in, this is needed when a swap happens
posMin = j;
}
}
//if pos_min no longer equals i than a smaller value must have been found, so a swap must occur
if (posMin != i) {
temp = list[i].PersonalNumber;
list[i].PersonalNumber = list[posMin].PersonalNumber;
list[posMin].PersonalNumber = temp;
}
}
}
If you want to sort list in place, just put Sort:
list.Sort((x, y) => x.PersonalNumber.CompareTo(y.PersonalNumber));
To sort in descending order, add -:
list.Sort((x, y) => -x.PersonalNumber.CompareTo(y.PersonalNumber));
It's definitely not something you should do manually (unless you're training your algorithmics skills :) ). It will make your code more complex and harder to maintain.
Just put:
using System.Linq;
and do this:
var sorted = list.OrderByDescending(x => x.PersonalNumber).ToList();
you don't need to be Linq ninja to use it. I also strongly recommend to start using it. I think you can agree it's very easy to read and quite obvious what is it doing.
Ah, and if you're wanting to sort ascending, just use .OrderBy instead of .OrderByDescending.
For most scenarios, you should use one of the built-in functionalities for sorting, such as List<T>.Sort or Enumerable.OrderBy. I'm assuming that you want to retain your own implementation for the sorting algorithm.
You can introduce a key selector function as the second argument to your method:
public static void SelectionSort<TSource, TKey>(
List<TSource> list,
Func<TSource, TKey> keySelector)
{
// With this method the list is sorted in ascending order.
//posMin is short for position of min
int posMin;
for (int i = 0; i < list.Count - 1; i++) {
posMin = i;//Set posMin to the current index of array
for (int j = i + 1; j < list.Count; j++) {
if (keySelector(list[j]) < keySelector(list[posMin])) {
//posMin will keep track of the index that min is in, this is needed when a swap happens
posMin = j;
}
}
//if pos_min no longer equals i than a smaller value must have been found, so a swap must occur
TSource temp;
if (posMin != i) {
temp = list[i];
list[i] = list[posMin];
list[posMin] = temp;
}
}
}
You would then consume this with a lambda expression:
SelectionSort(persons, (Person p) => p.PersonalNumber);
any one to help me solving this problem of mine?
I want to find biggest value inside a list inserted by keyboard something like this:
here it can be done by array:
int[] values = new int[10];
for (int i = 0; i < values.Length; i++)
{
values[i] = (int) (textbox.Text);
}
//to campare them
int bigValue=0;
for(int j=0;j<values.Lenght;j++)
{
if(bigValue<values[j])
{
bigValue==values[j];
}
}
////////////////////////////////
but in my code I have to use List I have filled the list but now I don't know the way to compare its values with each other to find the lowest and biggest one:
List<int> values= new List<int>();
values.Add((int)(textbox.Text));
Theres already built in functions for it, Max and Min:
int maxValue = values.Max();
int minValue = values.Min();
Your original function would work as well, substituting Count for Length, as indexing works with lists as well.
Use LINQ Min & Max functions:-
int LowestNumber = values.Min();
int HighestNumber = values.Max();
If you say you also need to use the list later in your program I guess you could find useful just to have it sorted.
values.Sort((value1, value2) => value1.CompareTo(value2));
With this option, minValue would be values[0] although the recomended way to find it is using the built in function as they have already mentioned.
You could just say something like this, which will work for any IEnumerable<int>, whether it's an int[], a List<int> or something else:
int? max = null ;
foreach( int value in someList )
{
max = (max??value) > value : (max??value) ;
}
At the end of this, If the list was empty, max will be null; otherwise max will have the highest value in the list.
In my code i have an arraylist called array.
I have filled it with numbers from 1 to 13
for(int i =1; i< 14; i++)
{
array.items.Add(i)
}
Later in my code I also remove some of the elements at random.
Example array.remove(3);
Now I wanna search, how many values of the elements
in the arraylist is over specific number.
So, how many elements in the arraylist is over for example 5.
Anyone who knows how to do this?
Thanks!
Use this lambda expression:
int count = array.Cast<int>().Where(e=> e > 5).Count();
or even simpler:
int count = array.Cast<int>().Count(e=> e > 5);
You must be from Java right? I believe that you should use a List<T> in c#.
int count = array.Cast<int>().Count(x => x > 5);
OR change your arrayList to be an enumerable to allow.
int count = array.Count(x => x > 5);
array.Cast<int>().Where(item => item > 5).Count();