Let's say that I have an array of strings like this:
1, 2, 3, 4, 5, 6, 7, 8
and I want to shift the elements of the array such that
The first element always remains fixed
Only the remaining elements get shifted like so ...
The last element in the array becomes the 2nd element and is shifted through the array with each pass.
Pass #1: 1, 2, 3, 4, 5, 6, 7, 8
Pass #2: 1, 8, 2, 3, 4, 5, 6, 7
Pass #3: 1, 7, 8, 2, 3, 4, 5, 6
Pass #4: 1, 6, 7, 8, 2, 3, 4, 5
Any assistance would be greatly appreciated.
Because this looks like homework, I'm posting an unnecessary complex, but very hip LINQ solution:
int[] array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
int[] result = array.Take(1)
.Concat(array.Reverse().Take(1))
.Concat(array.Skip(1).Reverse().Skip(1).Reverse())
.ToArray();
Probably the fastest way to do this in C# is to use Array.Copy. I don't know much about pointers in C# so there's probably a way of doing it that's even faster and avoids the array bounds checks and such but the following should work. It makes several assumptions and doesn't check for errors but you can fix it up.
void Shift<T>(T[] array) {
T last = array[array.Length-1];
Array.Copy(array, 1, array, 2, array.Length-2);
array[1]=last;
}
EDIT
Optionally, there is Buffer.BlockCopy which according to this post performs fewer validations but internally copies the block the same way.
Because this looks like homework, I'm not going to solve it for you, but I have a couple of suggestions:
Remember to not overwrite data if it isn't somewhere else already. You're going to need a temporary variable.
Try traversing the array from the end to the beginning. The problem is probably simpler that way, though it can be done from front-to-back.
Make sure your algorithm works for an arbitrary-length array, not just one that's of size 8, as your example gave.
Although sounds like homework like others suggest, if changing to a List<>, you can get what you want with the following...
List<int> Nums2 = new List<int>();
for( int i = 1; i < 9; i++ )
Nums2.Add(i);
for (int i = 1; i < 10; i++)
{
Nums2.Insert( 1, Nums2[ Nums2.Count -1] );
Nums2.RemoveAt(Nums2.Count -1);
}
Define this:
public static class Extensions
{
public static IEnumerable<T> Rotate<T>(this IEnumerable<T> enuml)
{
var count = enuml.Count();
return enuml
.Skip(count - 1)
.Concat(enuml.Take(count - 1));
}
public static IEnumerable<T> SkipAndRotate<T>(this IEnumerable<T> enuml)
{
return enum
.Take(1)
.Concat(
enuml.Skip(1).Rotate()
);
}
}
Then call it like so:
var array = new [] { 1, 2, 3, 4, 5, 6, 7, 8 };
var pass1 = array.SkipAndRotate().ToArray();
var pass2 = pass1.SkipAndRotate().ToArray();
var pass3 = pass2.SkipAndRotate().ToArray();
var pass4 = pass3.SkipAndRotate().ToArray();
There's some repeated code there that you might want to refactor. And of course, I haven't compiled this so caveat emptor!
This is similar to Josh Einstein's but it will do it manually and will allow you to specify how many elements to preserve at the beginning.
static void ShiftArray<T>(T[] array, int elementsToPreserve)
{
T temp = array[array.Length - 1];
for (int i = array.Length - 1; i > elementsToPreserve; i--)
{
array[i] = array[i - 1];
}
array[elementsToPreserve] = temp;
}
Consumed:
int[] array = { 1, 2, 3, 4, 5, 6, 7, 8 };
ShiftArray(array, 2);
First pass: 1 2 8 3 4 5 6 7
Related
Given a 1D array,
double[] arr = { 4, 3, 2, 8, 7, 6, 1 };
I want to get values from 2nd index till last and want to store the array in a variable.
Want to get something like this:
new_arr = {3, 2, 8, 7, 6, 1 }; //first element sliced
You can use C# 8 indices and ranges feature
double[] arr = { 4, 3, 2, 8, 7, 6, 1 };
var slice = arr[1..];
It'll return all items from index 1 till the end of array and give you an expected slice {3, 2, 8, 7, 6, 1 }. Again, it works only with C# 8 and .NET Core 3.x.
For earliest versions of C# you should do this by yourself, using Array.Copy for example or System.Linq
double[] arr = { 4, 3, 2, 8, 7, 6, 1 };
var slice = arr.Skip(1).ToArray();
If you are using C# 8, you can use Indices & Range. It goes something like this:
var newArray = oldArray[1..]; // Takes everything from index 1 until the end.
You can use Linq to skip the fist item and take the rest. This will give you the sequence:
arr.Skip(1);
Which you can convert to a new array like this:
var new_arr = arr.Skip(1).ToArray();
Here's an example of a solution I came up with
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
int[] arr = new int[] { 1, 2, 2, 3, 3, 3, 4, 4, 4, 4 };
var countlist = arr.Aggregate(new Dictionary<int,int>(), (D,i) => {
D[i] = D.ContainsKey(i) ? (D[i] + 1) : 1;
return D;
})
.AsQueryable()
.OrderByDescending(x => x.Value)
.Select(x => x.Key)
.ToList();
// print the element which appears with the second
// highest frequency in arr
Console.WriteLine(countlist[2]); // should print 3
}
}
At the very least, I would like to figure out how to
Cut down the query clauses by at least one. While I don't see any redundancy, this is the type of LINQ query where I fret about all the overhead of all the intermediate structures created.
Figure out how to not return an entire list at the end. I just want the 2nd element in the enumerated sequence; I shouldn't need to return the entire list for the purpose of getting a single element out of it.
int[] arr = new int[] { 1, 2, 2, 3, 3, 3, 4, 4, 4, 4 };
var lookup = arr.ToLookup(t => t);
var result = lookup.OrderByDescending(t => t.Count());
Console.WriteLine(result.ElementAt(1).Key);
I would do this.
int[] arr = new int[] { 1, 2, 2, 3, 3, 3, 4, 4, 4, 4 };
int rank =2;
var item = arr.GroupBy(x=>x) // Group them
.OrderByDescending(x=>x.Count()) // Sort based on number of occurrences
.Skip(rank-1) // Traverse to the position
.FirstOrDefault(); // Take the element
if(item!= null)
{
Console.WriteLine(item.Key);
// output - 3
}
I started to answer, saw the above answers and thought I'd compare them instead.
Here is the Fiddle here.
I put a stopwatch on each and took the number of ticks for each one. The results were:
Orignal: 50600
Berkser: 15970
Tommy: 3413
Hari: 1601
user3185569: 1571
It appears #user3185569 has a slightly faster algorithm than Hari and is about 30-40 times quicker than the OP's origanal version. Note is #user3185569 answer above it appears his is faster when scaled.
update: The numbers I posted above were run on my pc. Using .net fiddle to execute produces different results:
Orignal: 46842
Berkser: 44620
Tommy: 11922
Hari: 13095
user3185569: 16491
Putting the Berkser algortihm slightly faster. I'm not entirely clear why this is the case, as I'm targeting the same .net version.
I came up with the the following mash of Linq and a dictionary as what you're looking for is essentialy an ordered dictionary
void Run()
{
int[] arr = new int[] { 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4 };
int[] unique = arr.Distinct().ToArray();
Dictionary<int, int> dictionary = unique.ToDictionary(k => k, v => 0);
for(int i = 0; i < arr.Length; i++)
{
if(dictionary.ContainsKey(arr[i]))
{
dictionary[arr[i]]++;
}
}
List<KeyValuePair<int, int>> solution = dictionary.ToList();
solution.Sort((x,y)=>-1* x.Value.CompareTo(y.Value));
System.Console.WriteLine(solution[2].Key);
}
I have a list that I would like to add multiple elements to the start of. Adding to the start is linear time because it is backed by an array and has to be moved one at a time, and I cannot afford to do this as many times as I would have to if I implemented this the naive way.
If I know exactly how many elements I am about to add, can I shift them all that much so that the linearity only has to happen once?
List<int> myList = new List<int> { 6, 7, 8, 9, 10 };
//Desired list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
//Unacceptable
for (int i = 5; i>=0; i--){
myList.Insert(0,i);
}
//Is this concept possible?
int newElements = 5;
for (int i = myList.Count; i>=0; i--){
myList[i+newElements] = myList[i];//This line is illegal, Index was out of range
}
for (int i = 0; i< newElements; i++){
myList[i] = i+1;
}
In this specific instance, access needs to be constant time, hence the usage of List. I need to be able to add elements to both the start and end of the data structure as fast as possible. I am okay with O(m) where m is the number of elements being added (since I don't think that can be avoided) but O(m*n) where n is the number of elements in the existing structure is far too slow.
You can use InsertRange which will be linear if the inserted collection implements ICollection<T>:
var newElements = new[] { 0, 1, 2, 3, 4 };
myList.InsertRange(0, newElements);
myList.InsertRange(0, new List<int> { 1, 2, 3, 4, 5 });
If your new elements are already in a List, you could use List.AddRange to add your "old" list to the end of the to-be-added-items-list.
I would imagine myList.InsertRange(0, newElements) would suit you well. Microsoft will have made that as efficient as it can be.
I found similar topics, but I could not solve the problem I has reading them.
I want to do in C# the same thing like in C is array of pointers, but I do not want to use in C# pointers because it requires to use "unsafe".
How to build an array of " ref to int" that when I change any element of that array then I will also change that what it refs to at the same time the variable that it points to ( Like in C - array of pointers).
Best regards,
Chris
If performance is not a concern, than one common workaround is to use lambda to capture the access to value type variable:
Sample:
class GetSetPair<T>
{
public Func<T> Get {get;set;}
public Action<T> Set {get;set;}
}
var referencesToInt = new List<GetSetPair<int>>();
int value = 42;
referencesToInt.Add(new GetSetPair<int>{Get=()=>value, Set = v => value = v});
referencesToInt[0].Set(33);
Console.WriteLine(value); // 33
value = 22;
Console.WriteLine(referencesToInt[0].Get()); //22
Arrays are reference types, and therefore you can pass around references to that array. For example, given the following program:
public class Program
{
public static Random rnd = new Random();
public static int[] array2;
public static void Main()
{
int[] array = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
PrintArray(array);
array[4] = rnd.Next();
PrintArray(array);
ModArray(array, 2);
PrintArray(array);
array2 = array; //This makes array2 reference array1
ModArray(array2, 8); //Operate on the array2 reference
PrintArray(array); //Changes are reflected in array
PrintArray(array2); //And in array2
Console.ReadKey(true);
}
public static void PrintArray(int[] array)
{
foreach (var e in array)
Console.Write(e + ", ");
Console.WriteLine();
}
public static void ModArray(int[] array, int i)
{
array[i] = rnd.Next();
}
}
Will give the following output:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, <- Original
1, 2, 3, 4, 744477516, 6, 7, 8, 9, 10, <- Modified in Main
1, 2, 102109069, 4, 744477516, 6, 7, 8, 9, 10, <- Modified in ModArray
1, 2, 102109069, 4, 744477516, 6, 7, 8, 1776657318, 10, <- array, after modifying array2
1, 2, 102109069, 4, 744477516, 6, 7, 8, 1776657318, 10, <- array2
So in a sense, you can pass around a reference to the array, modify that reference, and have it reflected in all of its copies.
The caveat here is that anybody who "owns" a reference to the original array cannot reassign that array (or resize it). It can modify the elements of the array, but it can't make the original array point to a new instance (which is what happens when it is resized). Also, as Jon Skeet mentioned in his comment, the danger is that if you were doing this in a different method other than Main, if the array goes out of scope, what would happen to array2?
See Also:
Is int[] a reference type or a value type?
Are arrays or lists passed by default by reference in c#?
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
In a code review of a component library, I found syntax where some calculations for days per month are needed.
The simplified syntax is something like:
int preDays = (new int[] { 0, 1, 2, 3, 4, 5, 6 })[3] - 2;
Where [3] and -2 are variables. In the above example, the result of preDays is 1.
Could somebody please explain how we come to this result?
Break down the code into its individual pieces. Just like in math, we perform operations inside the parenthesis first, so you're creating an array of integers with the values 0 through 6. Next, the code looks at index 3 (arrays in C# are 0-based). The value at index 3 is 3. Lastly, we subtract 2 from 3 to get 1 and assign it to preDays.
You can think of it like this:
int[] myArray = { 0, 1, 2, 3, 4, 5, 6};
int myValue = myArray[3]; // Value is 3
int preDays = myValue - 2; // Value is 1
Does this help:
var array = new int[] { 0, 1, 2, 3, 4, 5, 6 };
int value = array[3]; //3
int preDays = value - 2; //1
This one's quite easy in my opinion:
within the () there's a new anonymous array defined. An array which consists of seven elements being 0,1,2,3,4,5 and 6. From this array you take the 4th element.
([3] refers to the fourth element as counting starts from [0] referring to the first element).
The fourth element of the array is 3, so the expression (new int[] { 0, 1, 2, 3, 4, 5, 6 })[3] resolves to 3. Subtracting 2 from 3 makes preDays to be filled with 1.
you are creating an array an making an arithmetic calculation on the same line and given that
index in c# has a zero as base so if you count 0,1,2,3 you will get a value 3 in the 4 case of the array so 3 minus 2 you will get 1
So take it like that
var myArray = new int[] { 0, 1, 2, 3, 4, 5, 6 };
int myValue = array[3]; //3
int preDays = value - 2;
In int preDays = (new int[] { 0, 1, 2, 3, 4, 5, 6 })[3] - 2;
(new int[] { 0, 1, 2, 3, 4, 5, 6 }) will create temporary integer array of size 7 and with values(0, 1, 2, 3, 4, 5, 6).
(new int[] { 0, 1, 2, 3, 4, 5, 6 })[3] will extract 4th item(item with index 3) i.e value 3.
(new int[] { 0, 1, 2, 3, 4, 5, 6 })[3] - 2 will perform 3 - 2 = 1.