Swap List<> elements with c# using LINQ - c#

I have this list
var list = new List { 3, 1, 0, 5 };
I want to swap element 0 with 2
output
0, 1, 3, 5

If you just want it sorted, I'd use List.Sort().
If you want to swap, there is no built in method to do this. It'd be easy to write an extension method, though:
static void Swap<T>(this List<T> list, int index1, int index2)
{
T temp = list[index1];
list[index1] = list[index2];
list[index2] = temp;
}
You could then do:
list.Swap(0,2);

Classic swap is...
int temp = list[0];
list[0] = list[2];
list[2] = temp;
I don't think Linq has any 'swap' functionality if that's what you're looking for.

In the case that something is not directly supported ...make it so number 1!
Take a look at the concept of "extension methods". With this you can easily make your list support the concept of Swap() (this applies to any time you want to extend the functionality of a class).
namespace ExtensionMethods
{
//static class
public static class MyExtensions
{
//static method with the first parameter being the object you are extending
//the return type being the type you are extending
public static List<int> Swap(this List<int> list,
int firstIndex,
int secondIndex)
{
int temp = list[firstIndex];
list[firstIndex] = list[secondIndex];
list[secondIndex] = temp;
return list;
}
}
}

Related

Why does one extension mutate but the other doesn't

I'm playing around with C# extensions and am confused about mutate methods.
Below are two code samples that are supposed to change the calling List. The first (shuffle) works but the second (CustomExtension) leaves the List unchanged.
At the end of the CustomExtension call the list parameter looks to be changed, but on returning from the method the List looks untouched.
Why does one work and the other doesn't? What's going on?
This works.
readonly private static Random rng = new Random();
public static void Shuffle<T>(this IList<T> list)
{
int n = list.Count;
while (n < 1)
{
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
myList.Shuffle();
(The above was ripped from Randomize a List<T>)
This Doesn't
static void CustomExtension(this IList<int> list)
{
list = new List<int>() { 9, 10, 11 };
}
foo.CustomExtension();
In the first example, you're overwriting elements inside the List<T>. This mutates the list in-place.
In the second example you're creating a new list and replacing the local reference list which is a parameter which is not being passed using ref, so it has no effect outside of the scope of the method. Your foo instance is not being mutated in CustomExtension.
Extension methods in C# cannot pass the this parameter using ref so you cannot overwrite the caller's instance reference.
If you change the method and call-site to a normal method with a ref parameter, then it works as expected (but it still isn't mutating foo, it's replacing it):
static void CustomExtension(ref IList<int> list)
{
list = new List<int>() { 9, 10, 11 };
}
CustomExtension( ref foo );

Using IComparable to compare arrays

I have a problem with a school task.
"Let's say class List are constructors to generate random arrays.
Class List1 inherits from class List and uses IComparable to compare first elements, then second ones etc. (blank is a 0) {1,1,1}<{1,2}<{2}
Class List2 inherits likewise and compares sizes of arrays by size. If sizes are the same, check like in List1 {1,2,3}<{1,2,3,4}<{2,2,3,4}"
I made class List.
public List(int b)
{
tabb = new int[b];
for (int i = 0; i < b; i++)
tabb[i] = r1.Next(0, 100);
}
I noticed that inheriting from List to List1 the constructors are not inherited, so i dont know where and how to use IComparable
class List1 : List,IComparable<List1>
{
public int CompareTo(List1 x){
return this.CompareTo(x);
}
}
I noticed that inheriting from List to List1 the constructors are not inherited, so i dont know where and how to use IComparable
I can't comprehend that sentence as a single question, as the lack of constructors being inherited seems completely independent to me of how to use IComparable<T>.
So, let's address the two questions separately:
You are correct that constructors are not inherited. That is, while they still exist, they are callable only by the derived type, and not directly usable by outside code. If a base class does not have a parameterless constructor, then as the implementer of the derived class, it is your responsibility to provide a constructor and then call the appropriate base class constructor (every class will have some constructor). For example:
class List1 : List
{
public List1(int count) : base(count) { }
}
(I'm assuming here that List is some type other than the .NET List<T> type, i.e. it's not generic and is defined in your own context.)
In this way, you provide the necessary constructor, and ensure that the correct base constructor is called, by using : base(count) to pass the parameter value to your constructor.
How to use IComparable<T>. It seems to me that this is the crux of your assignment. I would be doing you a disservice to write the code for you. However, I'll try to elaborate on the instructions to help you understand what they seem to be asking (of course, your teacher is the best person for you to receive this advice from).
You have two different assignments here. Both require that you implement the interface IComparable<T>, so the first thing you need to do is make sure you understand what it means to implement an interface. Do you? An interface is a kind of "contract". In any interface declaration, there are described the members that an implementation of that interface is required to provide. If you look at the definition of IComparable<T>, you'll see it requires implementation of just one member: a CompareTo() method.
So, your assignment comes down to how to implement that method for each of the two required subclasses, List1 and List2. The basic idea of the implementation is the same for both, but the specifics are different.
In the first case, the comparison will order the two instances of List1 according to the contents of the collection where the order of those instances is determined by the ordering of the first non-equal element in the same position of the array in each instance. In the examples given, {1, 1, 1} is treated as "less than" {1, 2} because when you compare the elements at each position for each instance of List1, the first corresponding position where the elements are different is the second position (index 1), where {1, 1, 1} has the value 1 and {1, 2} has the value 2. The value 1 is less than the value 2, so the whole instance of {1, 1, 1} is "less than" the whole instance of {1, 2}. (Unfortunately, the assignment as described in your post is not clear on how to order instances where the underlying list of one is shorter than the underlying list of the other, but has exactly the same values in those element positions. I would make the shorter list be treated as "less than", but that's not unambiguously the only valid way to do it.)
In the second part of the assignment, implementing List2, the only thing that's being compared is the length of the list. This should be much easier to implement than the first part of the assignment, because you have only a single value to compare in each List2 instance, i.e. tabb.Length.
Note that in both cases, you can take advantage of the fact that int also implements IComparable<T>, so you can use its CompareTo() method to determine whether corresponding values in each instance of your class are less than, equal to, or greater than each other.
I hope that that's enough to get you pointed in the right direction. If you need more help than that, you probably should just consult with your instructor. They will know exactly how much help they want to provide to you, while remaining short of actually doing the assignment for you.
Sorry, I didn't mean to go all out on this. But then it just happened. It's late. It interested me, especially the need to be able to test it even though the requirement for random numbers makes it difficult to test.
The solution I came do was to separate the list from how it gets populated. That way for test purposes I can substitute a "populator" that inserts exactly the values I want. That way I can create the scenarios for testing.
// This is the base list - it just requires something to populate it.
public class IntegerList : List<int>
{
public IntegerList(IIntegerListPopulator populator, int size)
{
populator.PopulateList(this, size);
}
}
// Interface and implementation to populate a list with random numbers.
public interface IIntegerListPopulator
{
void PopulateList(List<int> target, int size);
}
public class RandomIntegerListPopulator : IIntegerListPopulator
{
public void PopulateList(List<int> target, int size)
{
var random = new Random();
for (var i = 0; i < size; i++)
{
target.Add(random.Next(0, 100));
}
}
}
// Compares by values, but the populator is injected - needed so that
// the class can be tested.
public class IntegerListThatComparesByValues : IntegerList, IComparable<IntegerListThatComparesByValues>
{
public IntegerListThatComparesByValues(IIntegerListPopulator populator, int size)
: base(populator, size)
{ }
public int CompareTo(IntegerListThatComparesByValues other)
{
return new IntegerListValueComparer().Compare(this, other);
}
}
// Class to perform comparisons by value. There's no real point
// in implementing IComparer since I'm not using it that way,
// but it doesn't hurt.
public class IntegerListValueComparer : IComparer<IntegerList>
{
public int Compare(IntegerList x, IntegerList y)
{
// I made this part up. I don't actually know how
// you want to handle nulls.
if (x == null && y == null) return 0;
if (x == null) return 1;
if (y == null) return -1;
// Always compare the longer one to the shorter.
// if this one is shorter, do the reverse comparison
// and reverse the result.
if (y.Count < x.Count) return -Compare(y, x);
if (x.SequenceEqual(y)) return 0;
for (var index = 0; index < x.Count; index++)
{
var comparison = x[index].CompareTo(y[index]);
if (comparison != 0) return comparison;
}
// If the other list is longer than this one, then assume
// that the next element of this list is 0.
return -y[x.Count];
}
}
public class IntegerListThatComparesByLength : IntegerList, IComparable<IntegerListThatComparesByLength>
{
public IntegerListThatComparesByLength(IIntegerListPopulator populator, int size)
: base(populator, size)
{
}
public int CompareTo(IntegerListThatComparesByLength other)
{
var comparisonByCount = Count.CompareTo(other?.Count ?? 0);
return comparisonByCount != 0
? comparisonByCount
: new IntegerListValueComparer().Compare(this, other);
}
}
// *************************************************************
// These are the concrete classes specified in the requirements.
// *************************************************************
public class RandomIntegerListThatComparesByValues :
IntegerListThatComparesByValues
{
public RandomIntegerListThatComparesByValues(int size)
: base(new RandomIntegerListPopulator(), size)
{ }
}
public class RandomIntegerListThatComparesByLength :
IntegerListThatComparesByLength
{
public RandomIntegerListThatComparesByLength(int size)
: base(new RandomIntegerListPopulator(), size)
{ }
}
// *************************************************************
// The rest is all testing.
// *************************************************************
// Allows me to create class instances that contain the numbers
// I specify instead of random numbers so that I can create
// test cases.
public class IntegerListPopulatorTestDouble : IIntegerListPopulator
{
private readonly int[] _values;
public IntegerListPopulatorTestDouble(params int[] values)
{
_values = values;
}
public void PopulateList(List<int> target, int size)
{
target.AddRange(_values.Take(size));
}
}
[TestClass]
public class IntegerListThatComparesByValuesTests
{
[TestMethod]
public void EmptyListsAreEqual()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(), 0 );
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(), 0);
Assert.AreEqual(0, list1.CompareTo(list2));
}
[TestMethod]
public void ListsWithSameValuesAreEqual()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1,2,3), 3);
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1,2,3), 3);
Assert.AreEqual(0, list1.CompareTo(list2));
}
[TestMethod]
public void ListsOfSameLengthComparedByFirstNonEqualValue()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 4), 3);
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
Assert.IsTrue(list1.CompareTo(list2) > 0);
}
[TestMethod]
public void MissingElementsOfListAreSortedAsZeros()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3, 4), 4);
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
var comparison = list1.CompareTo(list2);
Assert.IsTrue(comparison > 0);
comparison = list2.CompareTo(list1);
Assert.IsTrue(comparison < 0);
}
[TestMethod]
public void MissingElementsOfListAreSortedAsZeros_Case2()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3, -4), 4);
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
Assert.IsTrue(list1.CompareTo(list2) < 0);
Assert.IsTrue(list2.CompareTo(list1) > 0);
}
}
[TestClass]
public class IntegerListThatComparesByLengthTests
{
[TestMethod]
public void ListsAreComparedByLength()
{
var list1 = new IntegerListThatComparesByLength(new IntegerListPopulatorTestDouble(1, 2, 3, 4), 4);
var list2 = new IntegerListThatComparesByLength(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
Assert.IsTrue(list1.CompareTo(list2) > 0);
Assert.IsTrue(list2.CompareTo(list1) < 0);
}
[TestMethod]
public void ListsOfEqualLengthAreComparedByValue()
{
var list1 = new IntegerListThatComparesByLength(new IntegerListPopulatorTestDouble(1, 2, 4), 3);
var list2 = new IntegerListThatComparesByLength(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
Assert.IsTrue(list1.CompareTo(list2) > 0);
Assert.IsTrue(list2.CompareTo(list1) < 0);
}
}
I don't know if they teach unit testing in school, but this illustrates why they should. While the logic isn't incredibly difficult, it's likely that the first stab at it isn't going to be perfect. Without creating some test cases to run against this, how could you know if you got it right? How would your instructor know? What if you fix one bug but in doing so break the other test case? And then if you have to debug, every single time you debug you get different random numbers. Scary.
(It was the randomness that really threw me off. If the numbers are always random, how does the instructor expect to observe the results and know that they're correct? It's possible but eyeballing it isn't the most reliable way to know that it works.)
In real life, I wouldn't want to put even slightly complex logic into a production system without having these unit tests to tell me that it works as expected.
Also, when you read a description of requirements it can be confusing and unclear. But assuming that I understood the requirements, now you can look at the unit tests and get a clearer idea of what this code is supposed to do. Otherwise someone else could need to make changes, and if they can't tell what it's supposed to do, they can't tell if they're breaking it. If it turns out that I got the requirements wrong then I can change the tests to fit the right requirements. The tests will fail and then I modify the code until the tests pass.

Create a method for adding and removing from an array in c#

I'm creating a C# class with array members that is supposed to work like a List.
I want something syntax that is similar to the following when adding a book to a book list.
book.Add(firstName = "Jack", lastName = "Reacher", title = "Dollar", year = 2005);
This book should now be added to an array.We keep track of all the books that we add to that array.
I also want to be able to write something like:
book.delete[2];
to delete the 3'rd book in from the array.
What would be the best way to accomplish this ?
From the perspective of OOP, a better way would just be to use the Generic List as pointed out by Shahrooz Jefri - and make a custom class or struct "Book", which would have member fields "string firstName", "string lastName", "string title", and "int year."
Then, juust make a list of books like this,
List<Book> books = new List<Book>();
books.Add(new Book("Jack","Reacher","Dollar",2005));
If you need to implement your own generic collection w/ static arrays, you can do something like:
public class MyList<T> {
private T[] internalArray;
private int capacity;
private int size;
public int Size { get { return size; } }
public MyList(){
this.size = 0;
this.capacity = 2; //put something you feel like is reasonable for initial capacity
internalArray = new T[2];
}
public void Add(T item){
int factor = 2; //some "growth" factor
if(this.size == this.capacity){
this.capacity *= factor;
T[] newArray = new T[this.capacity];
System.Array.Copy(this.internalArray, newArray, this.size);
this.internalArray = newArray;
}
this.internalArray[this.size] = item;
this.size ++;
}
public void RemoveAt(int index){
//write code that shifts all elements following index back by one
//decrement the size
//if necessary for mem. conservation, shrink the array capacity if half of less elements remain
}
}
Off course, then you'll have to overload the [] bracket operator for access, perhaps make it implement the Enumerable, etc.
You can use Linq to object and for collecrion use Generic List
List<int> list = new List<int>();
list.Add(2);
list.Add(3);
list.Add(5);
list.Add(7);
If you want to add and remove items at will, then an array might not be the best choice. Resizing arrays is relatively expensive; it is better to use something like a list (as suggested by Shahrooz Jefri).
Also, I would shift the add/remove operation away from the book itself and towards the collection. Better to do:
bookList.Add(...)
...than...
book.Add(...)

Pointing to array element

What I'm trying to achieve is say i have an array, i want to be able to modify a specific array element throughout my code, by pointing at it.
for example in C++ i can do this
int main(){
int arr [5]= {1,2,3,4,5};
int *c = &arr[3];
cout << arr[3] <<endl;
*c = 0;
cout << arr[3]<<endl;
}
I did some googling and there seems to be a way to do it through 'unsafe', but i don't really want to go that route.
I guess i could create a variable to store the indexes, but I'm actually dealing with slightly more complexity (a list within a list. so having two index variables seems to add complexity to the code.)
C# has a databinding class, so what I'm currently doing is binding the array element to a textbox (that i have hidden) and modifying that textbox whenever i want to modify the specific array element, but that's also not a good solution (since i have a textbox that's not being used for its intended purpose - a bit misleading).
A C# example of how you would like the use to look would help. If I understand what you're asking, a simple class like this might do it. What you're asking for though, doesn't seem like a very good idea. If you showed the larger scope in which you need this, someone might be able to point out a better design where you didn't need this sort of functionality at all.
public class ListElement<T> {
private IList<T> list;
private int index;
public ListElement(IList<T> list, int index) {
this.list = list;
this.index = index;
}
public T Value {
get {
return list[index];
}
set {
list[index] = value;
}
}
}
a use of this would look like
int[] arr = new int[] {1,2,3,4,5};
ListElement<int> third = new ListElement<int>(arr, 2);
Console.WriteLine(third.Value);
third.Value = 0;
Console.WriteLine(third.Value);
i'm not sure if this fits exactly, but the problem is that these pointers are not possible in c#.
if you have more complicated lists, you can take a look at LinkedList<T>
it provides a performant way if you want to change elements within a list.
I came up with a somewhat solution in C#. Granted this is off the cuff, so it may not work in all situations but I did test it briefly on your situation.
class Wrapper<T>
{
private T[] array;
private T item;
private int index;
public T Item { get { return item; } set { item = value;
array[Index] = value;
} }
public int Index
{
get { return index; }
set
{
index = value;
Item = array[value];
}
}
public Wrapper(T[] arr)
{
array = arr;
}
}
You can then use the class like this:
class Program
{
static void Main(string[] args)
{
int[] i = {1, 2, 3, 4, 5};
i.ToList().ForEach(x => Console.WriteLine(x));
Wrapper<int> w = new Wrapper<int>(i);
w.Index = 2;
w.Item = 5;
i.ToList().ForEach(x => Console.WriteLine(x));
Console.ReadLine();
}
}
This will give the output: 1234512545
It isn't as pretty as the solution in C++ but it will work as you want and provides a more "automatic" version of referencing the array.
I would wrap your arrays in Objects. In C#, stuff that needs pointer manipulation is usually best done with objects.
The advantage is that objects allow clearer naming and access to more complex data structures. You are right, it is not ideal to pass around sets of indices - the ordering and indexing is easily jumbled.. In fact, I think it was people in your position who decided Object-oriented programming would be a good idea!!
So you have class MyArray { }, and can use the 'object reference' as you would a pointer,
plus you can create arrays of MyArray[].

Shortest code to calculate list min/max in .NET

I'd like something like
int minIndex = list.FindMin(delegate (MyClass a, MyClass b) {returns a.CompareTo(b);});
Is there a builtin way to do this in .NET?
Try looking at these:
Min
Max
As long as your class implements IComparable, all you have to do is:
List<MyClass> list = new List();
//add whatever you need to add
MyClass min = list.Min();
MyClass max = list.Max();
Well, if you can't use .NET 3.5, you could always sort the list and then return list[0]. It might not be the fastest way, but it's probably the shortest code, especially if your class already implements IComparable.
List<SomeClass> list = new List<SomeClass>();
// populate the list
// assume that SomeClass implements IComparable
list.Sort();
return list[0]; // min, or
return list[list.Count - 1]; // max
This also assumes, of course, that it doesn't matter which item you return if you have multiple items that are the minimum or maximum.
If your class doesn't implement IComparable, you can pass in an anonymous delegate, something like this:
list.Sort(delegate(SomeClass x, SomeClass y) { return string.Compare(x.Name, y.Name); });
You note that "I'm still in 2" - you might, then, want to look at LINQBridge. This is actually aimed at C# 3.0 and .NET 2.0, but you should be able to use it with C# 2.0 and .NET 2.0 - just you'll have to use the long-hand:
MyClass min = Enumerable.Min(list),
max = Enumerable.Max(list);
Of course, it will be easier if you can switch to C# 3.0 (still targetting .NET 2.0).
And if LINQBridge isn't an option, you can implement it yourself:
static void Main()
{
int[] data = { 3, 5, 1, 5, 5 };
int min = Min(data);
}
static T Min<T>(IEnumerable<T> values)
{
return Min<T>(values, Comparer<T>.Default);
}
static T Min<T>(IEnumerable<T> values, IComparer<T> comparer)
{
bool first = true;
T result = default(T);
foreach(T value in values) {
if(first)
{
result = value;
first = false;
}
else
{
if(comparer.Compare(result, value) > 0)
{
result = value;
}
}
}
return result;
}
Using Linq you have the Min() and Max() functions.
So you can do list.AsQueryable().Min();

Categories

Resources