I have a 3D array int array
arr1 = new int[2,2,2];
I'd like to create another array, this time 2D, which would be a part of the arr1.
Sudo code:
arr2 = arr1[..,..,2]
.. means all elements
(create 2D array from arr1 for trird dimension (rank) index equals 2)
But it looks like there is no a range operator for arrays in C#. Am I right, or I overlooked something?
In other languages thre are some range operators marking all elements, for example: .. or :
I'd like to avoid iterate over arr1 array.
Strange that Google brings you to such an old question, but there are now range operators (..) for C# 8+
For example:
var testArray = new[] { a, b, c, d, e, f };
var a = testArray[..]; // gets all elements (a,b,c,d,e,f)
var b = testArray[0..3]; // gets first 3 elements (a,b,c)
var c = testArray[3..5]; // gets elements 3 and 4 (d,e)
var d = testArray[^3..]; // gets all elements starting from 3
// but count starts from the end, that is testArray.Length - 3 (d,e,f)
See more examples here:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/ranges
You can write your own extension
public static void getRange(this int[] array, int start, int end) {
//your for loop
}
Then use arr1.getRange(1,2)
But there is no builtin operator.
Related
C# why does binarysearch have to be made on sorted arrays and lists?
Is there any other method that does not require me to sort the list?
It kinda messes with my program in a way that I cannot sort the list for it to work as I want to.
A binary search works by dividing the list of candidates in half using equality. Imagine the following set:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
We can also represent this as a binary tree, to make it easier to visualise:
Source
Now, say we want to find the number 3. We can do it like so:
Is 3 smaller than 8? Yes. OK, now we're looking at everything between 1 and 7.
Is 3 smaller than 4? Yes. OK, now we're looking at everything between 1 and 3.
Is 3 smaller than 2? No. OK, now we're looking at 3.
We found it!
Now, if your list isn't sorted, how will we divide the list in half? The simple answer is: we can't. If we swap 3 and 15 in the example above, it would work like this:
Is 3 smaller than 8? Yes. OK, now we're looking at everything between 1 and 7.
Is 3 smaller than 4? Yes. OK, now we're looking at everything between 1 and 3 (except we swapped it with 15).
Is 3 smaller than 2? No. OK, now we're looking at 15.
Huh? There's no more items to check but we didn't find it. I guess it's not in the list.
The solution is to use an appropriate data type instead. For fast lookups of key/value pairs, I'll use a Dictionary. For fast checks if something already exists, I'll use a HashSet. For general storage I'll use a List or an array.
Dictionary example:
var values = new Dictionary<int, string>();
values[1] = "hello";
values[2] = "goodbye";
var value2 = values[2]; // this lookup will be fast because Dictionaries are internally optimised inside and partition keys' hash codes into buckets.
HashSet example:
var mySet = new HashSet<int>();
mySet.Add(1);
mySet.Add(2);
if (mySet.Contains(2)) // this lookup is fast for the same reason as a dictionary.
{
// do something
}
List exmaple:
var list = new List<int>();
list.Add(1);
list.Add(2);
if (list.Contains(2)) // this isn't fast because it has to visit each item in the list, but it works OK for small sets or places where performance isn't so important
{
}
var idx2 = list.IndexOf(2);
If you have multiple values with the same key, you could store a list in a Dictionary like this:
var values = new Dictionary<int, List<string>>();
if (!values.ContainsKey(key))
{
values[key] = new List<string>();
}
values[key].Add("value1");
values[key].Add("value2");
There is no way you use binary search on unordered collections. Sorting collection is the main concept of the binary search. The key is that on every move u take the middle index between l and r. On first step they are 0 and size - 1, after every step one of them becomes middle index between them. If x > arr[m] then l becomes m + 1, otherwise r becomes m - 1. Basically, on every step you take half of the array you had and, of course, it remains sorted. This code is recursive, if you don't know what recursion is(which is very important in programming), you can review and learn here.
// C# implementation of recursive Binary Search
using System;
class GFG {
// Returns index of x if it is present in
// arr[l..r], else return -1
static int binarySearch(int[] arr, int l,
int r, int x)
{
if (r >= l) {
int mid = l + (r - l) / 2;
// If the element is present at the
// middle itself
if (arr[mid] == x)
return mid;
// If element is smaller than mid, then
// it can only be present in left subarray
if (arr[mid] > x)
return binarySearch(arr, l, mid - 1, x);
// Else the element can only be present
// in right subarray
return binarySearch(arr, mid + 1, r, x);
}
// We reach here when element is not present
// in array
return -1;
}
// Driver method to test above
public static void Main()
{
int[] arr = { 2, 3, 4, 10, 40 };
int n = arr.Length;
int x = 10;
int result = binarySearch(arr, 0, n - 1, x);
if (result == -1)
Console.WriteLine("Element not present");
else
Console.WriteLine("Element found at index "
+ result);
}
}
Output:
Element is present at index 3
Sure there is.
var list = new List<int>();
list.Add(42);
list.Add(1);
list.Add(54);
var index = list.IndexOf(1); //TADA!!!!
EDIT: Ok, I hoped the irony was obvious. But strictly speaking, if your array is not sorted, you are pretty much stuck with the linear search, readily available by means of IndexOf() or IEnumerable.First().
This is my first question on this site. I am practicing on a problem on Hackerrank that asks to find numbers "Between two Sets". Given two arrays of integers, I must find the number(s) that fit the following two criteria:
1) The elements in the first array must all be factors of the number(s)
2) The number(s) must factor into all elements of the second array
I know that I need to find all common multiples of every element in the first array, but those multiples need to be less than or equal to the minimum value of the second array. I first sort the first array then find all the multiples of ONLY the largest number in the first array (again, up to a max of the second array's minimum) and store those multiples in a list. Then, I move on to the second largest element in the first array and test it against the array of existing multiples. All elements in the list of existing multiples that isn't also a multiple of the second largest element of the first array is removed. I then test the third largest value of the first array, all the way to the minimum value. The list of existing multiples should be getting trimmed as I iterate through the first array in descending order. I've written a solution which passes only 5 out of the 9 test cases on the site, see code below. My task was to edit the getTotalX function and I created the getCommonMultiples function myself as a helper. I did not create nor edit the main function. I am not sure why I am not passing the other 4 test cases as I can't see what any of the test cases are.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Solution {
/*
* Complete the getTotalX function below.
*/
static int getTotalX(int[] a, int[] b) {
//get minimum value of second array
int b_min = b.Min();
//create List to hold multiples
List<int> multiples = getCommonMultiples(a, b_min);
//create List to hold number of ints which are in solution
List<int> solutions = new List<int>();
foreach(int x in multiples)
{
foreach(int y in b)
{
if (y % x == 0 && !solutions.Contains(x))
{
solutions.Add(x);
}
else
{
break;
}
}
}
return solutions.Count;
}
static List<int> getCommonMultiples(int[] array, int max)
{
//make sure array is sorted
Array.Sort(array);
int x = array.Length - 1; //x will be the last # in array -- the max
int y = 1;
//find all multiples of largest number first and store in a list
int z = array[x] * y;
List<int> commonMultiples = new List<int>();
while(z <= max)
{
commonMultiples.Add(z);
y++;
z = array[x] * y;
}
//all multiples of largest number are now added to the list
//go through the smaller numbers in query array
//only keep elements in list if they are also multiples of smaller
//numbers
int xx = array.Length - 2;
for(int a = array[xx]; xx >= 0; xx--)
{
foreach(int b in commonMultiples.ToList())
{
if (b % a != 0)
{
commonMultiples.Remove(b);
}
else
{
continue;
}
}
}
return commonMultiples;
}
static void Main(string[] args) {
TextWriter tw = new StreamWriter(#System.Environment.GetEnvironmentVariable("OUTPUT_PATH"), true);
string[] nm = Console.ReadLine().Split(' ');
int n = Convert.ToInt32(nm[0]);
int m = Convert.ToInt32(nm[1]);
int[] a = Array.ConvertAll(Console.ReadLine().Split(' '), aTemp => Convert.ToInt32(aTemp))
;
int[] b = Array.ConvertAll(Console.ReadLine().Split(' '), bTemp => Convert.ToInt32(bTemp))
;
int total = getTotalX(a, b);
tw.WriteLine(total);
tw.Flush();
tw.Close();
}
}
Again, I can't see the test cases so I do not know what exactly the issue is. I went through the code line by line and can't find any OutOfBoundExceptions or things of that sort so it has to be a logic issue. Thanks for the help!
A typical sample involves 3 lines of input. The first line has 2 integers which gives the length of the first array and the second array, respectively. The second line will give the integers in the first array. The third line will give the integers in the second array. The output needs to be the total number of integers "in between" the two arrays. It will looks like this:
Sample Input
2 3
2 4
16 32 96
Sample Output
3
Explanation: 2 and 4 divide evenly into 4, 8, 12 and 16.
4, 8 and 16 divide evenly into 16, 32, 96.
4, 8 and 16 are the only three numbers for which each element of the first array is a factor and each is a factor of all elements of the second array.
I see two issues with the code you posted.
Firstly, as #Hans Kesting pointed out, a = array[xx] is not being updated each time in the for loop. Since the variable a is only used in one spot, I recommend just replacing that use with array[xx] and be done with it as follows:
for(int xx = array.Length - 2; xx >= 0; xx--)
{
foreach(int b in commonMultiples.ToList())
{
if (b % array[xx] != 0)
{
commonMultiples.Remove(b);
For your understanding of for loops: to properly increment a each time you'd write the for loop like this:
for(int xx = array.Length - 2, a = array[xx]; xx >= 0; xx--, a = array[xx])
The first part of the for loop (up until ;) is the initialization stage which is only called before the entering the loop the first time. The second part is the while condition that is checked before each time through loop (including the first) and if at any time it evaluates to false, the loop is broken (stopped). The third part is the increment stage that is called only after each successful loop.
Because of that in order to keep a up to date in the for loop head, it must appear twice.
Secondly, your solutions in getTotalX is additive, meaning that each multiple that works for each value in array b is added as a solution even if it doesn't fit the other values in b. To get it to work the way that you want, we have to use a Remove loop, rather than an Add loop.
List<int> multiples = getCommonMultiples(a, b_min);
//create List to hold number of ints which are in solution
List<int> solutions = multiples.ToList();
foreach(int x in multiples)
{
foreach(int y in b)
{
if (y % x != 0)
{
solutions.Remove(x);
break;
}
}
}
You could also use LINQ to perform an additive solution where it takes into account All members of b:
//create List to hold number of ints which are in solution
List<int> solutions = multiples.Where((x) => b.All((y) => y % x == 0)).ToList();
I needed to write a function that finds N highest numbers in an array.
I tried nothing. Don't even know where to start.
public int marathon(int input1,int input2, int[] input3)
{
// this is the function, ignore first input its not relevant input 2 is
// N(How much highest numbers you want from array )
}
If you put 2 as input2 and array looks like this {1,2,3,4} output will be 3 and 4
A little lambda will do the trick.
var top = new[] { 1, 2, 3, 4 }.OrderByDescending(num => num).Take(N);
By LINQ: Simply sort the array and take the first N items. Example of an extension method to do that:
public static class ExtensionMethods
{
public static IEnumerable<T> TakeHighests<T>(this IEnumerable<T> collection, int count)
{
return collection.OrderByDescending(i => i) // Sort the enumerable (arrays are also enumerables). Use OrderBy() for N lowest items
.Take(count) // Take only `count` items
}
}
Sample using of taking 2 highest values:
int[] arr = ...;
int[] twoHighests = arr.TakeHighests(2).ToArray();
Is there a potential 1 liner that allows me to create a new 1 dimensional array from a certain index of the inner array of the 2D?
Example take the first element of each inner array:
double[][] array2D = new double[10][] // with inner arrays say double[5]
double[] array1D = new double[10];
for (int i=0; i<array2D.Length; i++)
{
array1D[i] = array2D[i][0];
}
I'd just use LINQ. That won't "avoid loops" in terms of execution, but it'll avoid a loop in your source code:
// 1dArray isn't a valid identifier...
var singleArray = jaggedArray.Select(x => x[0]).ToArray();
Note that this relies on it being a jagged array (an array of arrays). It will not do what you expect for true multi-dimensional (rectangular) arrays.
Or slightly more efficiently:
var singleArray = Array.ConvertAll(jaggedArray, x => x[0]);
That's more efficient because it knows the output size to start with, and builds the array directly - but it's a bit less idiomatic than using LINQ these days (which is more generally applicable to all sequences, not just arrays).
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I convert a list<> to a multi-dimensional array?
I want to have an array in form of double[,] for this purpose since I do not know what will be the length of this array, I want to make a List first then later using List<T>.ToArray() convert it to double[,]:
public double[,] FilterClampedData(double[,] data)
{
var finalData = new List<double[]>();
//Do some stuff on parameter
return finalData.ToArray(); ///Does not compile :(
}
Since ToArray returns a one-dimensional array, there is no wonder why this does not compile. If you were returning double[][], it would compile, however. You could also build your 2-D array manually with two nested loops:
var R = finalData.Count;
var C = finalData[0].Length;
var res = new double[R, C];
for (int r = 0 ; r != R ; r++)
for (int c = 0 ; c != C ; c++)
res[r, c] = finalData[r][c];
return res;
The code above assumes that you have at least one item in the finalData, and that the length of all lists inside finalData is the same.
Instantiate a new double array with the largest size [length of the list, largest array length in the list]
Walk through the list with double for cycle (first on the list, the nested on the current list item) and fill the new array
finalData.ToArray() will produce double[][] because:
List<T>.ToArray() returns T[]
List<T[]>.ToArray() returns T[][]