I'm hoping this will be fairly simple and down to my lack of knowledge as a beginner but I'm trying to see if an array of ints with two elements is in a List.
Int[] meh = {1,2};
List<int[]> list1 = new List<int[]>();
List1.Add(meh);
Int[] meh2 = {1,2};
If(List1.Contains(meh2))
{
Console.WriteLine(“Found it”);
}
From reading around I gather that the array wont be found as it's to do with how Lists compare objects by reference and not value ... all examples Ive found have been to find a single int within an array in a List but not the array as a whole.
Im vaguely aware that List.Find() may be useful here but again I cant see how to use LINQ for matching both elements in each array in the list.
Any help or pointers to reading material greatly appreciated.
Thanks in advance.
How about this
if(list1.Any(x => x.SequenceEqual(meh2)))
{
Console.WriteLine("Found it");
}
You can use Enumerable.SequenceEqual
that will return -1 if the sequence is not found
example:
var myArr = new int[] { 3, 3 };
List<int[]> ListOfArrays = new List<int[]>
{
new int[] { 0, 0 },
new int[] { 2, 2 },
new int[] { 1, 1 },
new int[] { 3, 3 }
};
var index = ListOfArrays.FindIndex(l => Enumerable.SequenceEqual(myArr, l));
Console.WriteLine("here: " + index);
Not sure what you want to achieve exactly. If list1 has an element [1, 2, 3] and you search for [1, 2], would that be a match, or do all elements have to match? Do they have to be in the same order? ...
Whatever you want to achieve exactly, you can do it with Any() and SequenceEqual()
int[] meh = {1, 2};
int[] meh2 = {1, 5};
var list1 = new List<int[]>() {meh, meh2};
if (list1.Any(x => x.SequenceEqual(new[] {1, 5})))
{
Console.WriteLine("Found it");
}
Also see this answer. It contains an example where both arrays are sorted first (ie ignoring the order of the elements in the array)
Related
I would like to create a PriorityQueue to store int[]. The first element in the array is gonna be the criteria for the comparisons.
I could do that easily in Java, though I could not convert it to C#. Could you please guide me?
Priority queues don't work the same way in both languages. What you're trying to do is the Java way of giving PQ a lambda (function) to compare any two elements. In C#, you give each element a priority when adding it to the queue, and then make a comparer to compare different priorities.
PriorityQueue<int[], int> pq = new(Comparer<int>.Create((a, b) => a - b));
// The Comparer compares the *priorities*, not the elements
pq.Enqueue(new int[] { 1, 2, 3, 4 }, 5);
pq.Enqueue(new int[] { 1, 2, 3, 4 }, 0); // This has more priority
while (pq.TryDequeue(out int[]? arr, out int priority))
{
Console.WriteLine(priority); // 0; 5
}
You may be interested in just a simple List and LINQ:
using System.Linq; // at the top of your code to include LINQ
List<int[]> list = new();
list.Add(new int[] { 1, 2, 3, 4 });
list.Add(new int[] { 5, 2, 3, 4 });
IEnumerable<int[]> ordered = list.OrderBy(x => x[0]); // orders by the first element
So, i have a set of integers in an list
public List<int> numbers = new List<int>() { 3, 7, 6, 9, 8, 10, 11 }
what i am wanting to do is change those numbers so they are ordered between 0 and 6, to set as siblingindexs.
and then would be changed to become
public List<int> newArrangedNumbers = new List<int>() {0, 2, 1, 4, 3, 5, 6}
But im really not sure how to do this... Anyone know?
P.S. i cant rearrange the numbers because then i would lose track of the game objects since the numbers themselves aren't actually in an array, but i have gameobjects in an array, and i find the "SortIndex" of each gameobject, which are the numbers from above, the order of the numbers in the array is actually the order of GameObjects in the array, which i need to keep the same.
Edit: i also cannot change them to float values because for some reason, when using SetSiblingIndex(int), you have to integers, you cant use floats
Edit 2: i am NOT trying to sort the numbers, i am trying to CONVERT the numbers from 3-11 into 0-6 in ORDER
From:
{3, 7, 6, 9, 8, 10, 11}
To:
{0, 2, 1, 4, 3, 5, 6}
Edit 3: Here is my script for testing
List<int> Indexs = new List<int>() { 4, 7, 56, 9, 65, 67, 8, 3, 6 };
var sorted = Indexs.Select((x, i) => new KeyValuePair<int, int>(x, i)).OrderBy(x => x.Key).ToList();
List<int> newArrangedNumbers = sorted.Select(x => x.Value).ToList();
for(int i = 0; i < newArrangedNumbers.Count; i++)
{
Debug.Log(Indexs[i] + " : " + newArrangedNumbers[i]);
}
When i only had 7 (0-6) indexs in the "Indexs" List it worked fine, but when i added any more, it started giving me the incorrect numbers
This is what it gives with this
Here is a good method to achieve your desired output from this stack form C# Sort list while also returning the original index positions?
The modified code for your solution is below.
//The original list
List<int> numbers = new List<int>() { 3, 7, 6, 9, 8, 10, 11 };
var sorted = numbers
.Select((x, i) => new KeyValuePair<int, int>(x, i))
.OrderBy(x => x.Key)
.ToList();
//The sorted list
List<int> numbersSorted = sorted.Select(x => x.Key).ToList();
//List of indexes sorted based on the list above
List<int> newArrangedNumbers = sorted.Select(x => x.Value).ToList();
Edit
Since you sort the list, but also retrieve the sorted indexes based on the list you just sorted, you aren't going to have any mixup with your game objects.
It sounds like you want to find positions of each element in a sorted list of the same items.
So sort and find where element is and assign the index. Code sample below assumes unique numbers:
var sorted = numbers.OrderBy(x=>x).ToArray();
var result = new int[numbers.Count];
for (var i = 0; i < numbers.Count; i++)
{
var index = number.IndexOf(sorted[i]);
result[index] = i;
}
Notes
for anything about 5-10 items I'd use dictionary instead of IndexOf if you want to stick with this code.
if numbers are not unique or performance is critical you need to use solution by Aaron Jones that eventually will track original indexes even if it is harder to understand.
I have a list and an array. I want to find out the number/count of elements in the array that match those in the list
List<int> list = new List<int>{ 1, 2, 3, 4 };
int[] array = new int[] { 1, 2 };
Since the two matching elements are 1 and 2, I am expecting a result of count 2.
Can someone please point me in the right direction?
You can use a little Linq with the Count extension method:
var count = array.Count(list.Contains);
Or if you know that there are no duplicate values in the the array, you can use the Intersect method:
var count = array.Intersect(list).Count();
You can use:
int matches = list.Intersect(array).Count();
Note that this will only work if the list and array only contain unique values.
In C# I have three arrays, string[] array1, 2 and 3 and they all have differnt values. I would love to do what I can do in php which is:
$array = array();
$array[] .= 'some value';
Whats the equivalent way of doing this in C#?
In C#, you'd typically use a List<string> instead of string[].
This will allow you to write list.Add("some value") and will "grow" the list dynamically.
Note that it's easy to convert between a list and an array if needed. List<T> has a constructor that takes any IEnumerable<T>, including an array, so you can make a list from an array via:
var list = new List<string>(stringArray);
You can convert a list to an array via:
var array = list.ToArray();
This is only required if you need an array, however (such as working with a third party API). If you know you're going to work with collections that vary in size, it's often better to just always stick to List<T> and not use arrays.
You can create a list and add the array values to it and then convert that list back to array.
int[] array1 = { 1, 2, 3, 4, 5 };
int[] array2 = { 6, 7, 8, 9, 10 };
// Create new List of integers and call AddRange twice
var list = new List<int>();
list.AddRange(array1);
list.AddRange(array2);
// Call ToArray to convert List to array
int[] array3 = list.ToArray();
You could use dinamic lists List<string>. You can do
List<string> TotalList = array1.ToList();
Then you can TotalList.AddRange(array2) and so on....
List<T> or LINQ may be the easiest solutions, but you can also do it the old fashioned way:
// b1 is now 5 bytes
byte[] b1 = Get5BytesFromSomewhere();
// creating a 6-byte array
byte[] temp = new byte[6];
// copying bytes 0-4 from b1 to temp
Array.copy(b1, 0, temp, 0, 5);
// adding a 6th byte
temp[5] = (byte)11;
// reassigning that temp array back to the b1 variable
b1 = temp;
if you simply want to merge your arrays
use linq .Concat
array1 = array1.Concat(array2).Concat(array3).ToArray();
Easy with linq:
int[] array1 = { 1, 2, 3, 4, 5 };
int[] array2 = { 6, 7, 8, 9, 10 };
int[] array3 = { 3, 4 ,5, 9, 10 };
var result = array1
.Concat(array2)
.Concat(array3)
.ToArray();
I have two List's which I want to check for corresponding numbers.
for example
List<int> a = new List<int>(){1, 2, 3, 4, 5};
List<int> b = new List<int>() {0, 4, 8, 12};
Should give the result 4.
Is there an easy way to do this without too much looping through the lists?
I'm on 3.0 for the project where I need this so no Linq.
You can use the .net 3.5 .Intersect() extension method:-
List<int> a = new List<int>() { 1, 2, 3, 4, 5 };
List<int> b = new List<int>() { 0, 4, 8, 12 };
List<int> common = a.Intersect(b).ToList();
Jeff Richter's excellent PowerCollections has Set with Intersections. Works all the way back to .NET 2.0.
http://www.codeplex.com/PowerCollections
Set<int> set1 = new Set<int>(new[]{1,2,3,4,5});
Set<int> set2 = new Set<int>(new[]{0,4,8,12});
Set<int> set3 = set1.Intersection(set2);
You could do it the way that LINQ does it, effectively - with a set. Now before 3.5 we haven't got a proper set type, so you'd need to use a Dictionary<int,int> or something like that:
Create a Dictionary<int, int> and populate it from list a using the element as both the key and the value for the entry. (The value in the entry really doesn't matter at all.)
Create a new list for the intersections (or write this as an iterator block, whatever).
Iterate through list b, and check with dictionary.ContainsKey: if it does, add an entry to the list or yield it.
That should be O(N+M) (i.e. linear in both list sizes)
Note that that will give you repeated entries if list b contains duplicates. If you wanted to avoid that, you could always change the value of the dictionary entry when you first see it in list b.
You can sort the second list and loop through the first one and for each value do a binary search on the second one.
If both lists are sorted, you can easily do this in O(n) time by doing a modified merge from merge-sort, simply "remove"(step a counter past) the lower of the two leading numbers, if they are ever equal, save that number to the result list and "remove" both of them. it takes less than n(1) + n(2) steps. This is of course assuming they are sorted. But sorting of integer arrays isn't exactly expensive O(n log(n))... I think. If you'd like I can throw together some code on how to do this, but the idea is pretty simple.
Tested on 3.0
List<int> a = new List<int>() { 1, 2, 3, 4, 5, 12, 13 };
List<int> b = new List<int>() { 0, 4, 8, 12 };
List<int> intersection = new List<int>();
Dictionary<int, int> dictionary = new Dictionary<int, int>();
a.ForEach(x => { if(!dictionary.ContainsKey(x))dictionary.Add(x, 0); });
b.ForEach(x => { if(dictionary.ContainsKey(x)) dictionary[x]++; });
foreach(var item in dictionary)
{
if(item.Value > 0)
intersection.Add(item.Key);
}
In comment to question author said that there will be
Max 15 in the first list and 20 in the
second list
In this case I wouldn't bother with optimizations and use List.Contains.
For larger lists hash can be used to take advantage of O(1) lookup that leads to O(N+M) algorithm as Jon noted.
Hash requires additional space. To reduce memory usage we should hash shortest list.
List<int> a = new List<int>() { 1, 2, 3, 4, 5 };
List<int> b = new List<int>() { 0, 4, 8, 12 };
List<int> shortestList;
List<int> longestList;
if (a.Count > b.Count)
{
shortestList = b;
longestList = a;
}
else
{
shortestList = a;
longestList = b;
}
Dictionary<int, bool> dict = new Dictionary<int, bool>();
shortestList.ForEach(x => dict.Add(x, true));
foreach (int i in longestList)
{
if (dict.ContainsKey(i))
{
Console.WriteLine(i);
}
}
var c = a.Intersect(b);
This only works in 3.5 saw your requirement my apologies.
The method recommended by ocdecio is a good one if you're going to implement it from scratch. Looking at the time complexity compared to the nieve method we see:
Sort/binary search method:
T ~= O(n log n) + O(n) * O(log n) ~= O(n log n)
Looping through both lists (nieve method):
T ~= O(n) * O(n) ~= O(n ^ 2)
There may be a quicker method, but I am not aware of it. Hopefully that should justify choosing his method.
(Previous answer - changed IndexOf to Contains, as IndexOf casts to an array first)
Seeing as it's two small lists the code below should be fine. Not sure if there's a library with an intersection method like Java has (although List isn't a set so it wouldn't work), I know as someone pointed out the PowerCollection library has one.
List<int> a = new List<int>() {1, 2, 3, 4, 5};
List<int> b = new List<int>() {0, 4, 8, 12};
List<int> result = new List<int>();
for (int i=0;i < a.Count;i++)
{
if (b.Contains(a[i]))
result.Add(a[i]);
}
foreach (int i in result)
Console.WriteLine(i);
Update 2: HashSet was a dumb answer as it's 3.5 not 3.0
Update: HashSet seems like the obvious answer:
// Method 2 - HashSet from System.Core
HashSet<int> aSet = new HashSet<int>(a);
HashSet<int> bSet = new HashSet<int>(b);
aSet.IntersectWith(bSet);
foreach (int i in aSet)
Console.WriteLine(i);
Here is a method that removed duplicate strings. Change this to accomidate int and it will work fine.
public List<string> removeDuplicates(List<string> inputList)
{
Dictionary<string, int> uniqueStore = new Dictionary<string, int>();
List<string> finalList = new List<string>();
foreach (string currValue in inputList)
{
if (!uniqueStore.ContainsKey(currValue))
{
uniqueStore.Add(currValue, 0);
finalList.Add(currValue);
}
}
return finalList;
}
Update: Sorry, I am actually combining the lists and then removing duplicates. I am passing the combined list to this method. Not exactly what you are looking for.
Wow. The answers thus far look very complicated. Why not just use :
List<int> a = new List<int>() { 1, 2, 3, 4, 5, 12, 13 };
List<int> b = new List<int>() { 0, 4, 8, 12 };
...
public List<int> Dups(List<int> a, List<int> b)
{
List<int> ret = new List<int>();
foreach (int x in b)
{
if (a.Contains(x))
{
ret.add(x);
}
}
return ret;
}
This seems much more straight-forward to me... unless I've missed part of the question. Which is entirely possible.