We have two arrays of integers a1 and a2 as parameters and we should remove all occurrences of a2 values from a1. Element is "removed" by shifting all subsequent elements one index to the left to cover it up, placing a 0 into the last index. The original relative ordering of a1 elements should be retained.
i'm having problem with shifting it's element.
Example:
int[] a1 = { 42, 3, 9, 42, 42, 0, 42, 9, 42, 42, 17, 8, 2222, 4, 9, 0, 1};
int[] a2 = { 42, 2222, 9};
the final result should be like this:
{3, 0, 17, 8, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
so here is my code:
for(int i = 0; i < a1.Length; i++)
{
foreach(var element in a2)
{
if (element == a1[i])
{
for(int j = i; j < a1.Length-1; j++)
{
a1[j] = a1[j+1];
}
a1[a1.Length - 1] = 0;
}
}
}
You need to use i--; when your item matches. Because you're shifting your entire array. Also you need to use break; your inner foreach loop after i--;.
Explanation
1) With your arrays, for i = 0 and first element in foreach(var element in a2) both will be 42. So first your array will be shifted one index. Now if you are not using i-- then it will check for i=1 which should be 3 but as we already shifted our array so 3 value is at index 0. So this value will never getting checked for match.
2) And use of break, as your match already found and array is shifted there is no requirement for check further.
Your code should be like below.
for(int i = 0; i < a1.Length; i++)
{
foreach(var element in a2)
{
if (element == a1[i])
{
for(int j = i; j < a1.Length-1; j++)
{
a1[j] = a1[j+1];
}
a1[a1.Length - 1] = 0;
i--;
break;
}
}
}
If You can use Linq then try as below, First get filters elements first. Then add 0 for rest indexes.
int[] a1= { 42,3,9,42,42,0,42,9,42,42,17,8,2222,4,9,0,1};
int[] a2= { 42,2222,9};
var a3 = a1.Where(x => !a2.Contains(x)).ToArray();
for (int i = 0; i < a1.Length; i++) {
if (i < a3.Length)
a1[i] = a3[i];
else
a1[i] = 0;
}
You can do this without creating any extra arrays like so:
static void Main()
{
int[] a1 = { 42, 3, 9, 42, 42, 0, 42, 9, 42, 42, 17, 8, 2222, 4, 9, 0, 1 };
int[] a2 = { 42, 2222, 9 };
int j = 0;
for (int i = 0; i < a1.Length; ++i)
if (Array.IndexOf(a2, a1[i]) < 0) // Don't remove this value.
a1[j++] = a1[i];
Array.Clear(a1, j, a1.Length-j);
Console.WriteLine(string.Join(", ", a1));
}
We make two passes: Firstly to remove all the elements of a1 that are contained in a2 (via the explicit loop) and then to overwrite all the "removed" values with 0 (via Array.Clear().
Just a different approach by first filtering and then adding the needed zeros:
int[] a1 = { 42, 3, 9, 42, 42, 0, 42, 9, 42, 42, 17, 8, 2222, 4, 9, 0, 1 };
int[] a2 = { 42, 2222, 9 };
var zeros = Enumerable.Repeat(0, int.MaxValue);
var valids = a1.Where(v => !a2.Contains(v));
var result = valids.Concat(zeros).Take(a1.Length);
Console.WriteLine(String.Join(", ", result));
Yet another approach, using Array.Copyfor shifting:
public static void Main()
{
int[] a1 = { 42, 3, 9, 42, 42, 0, 42, 9, 42, 42, 17, 8, 2222, 4, 9, 0, 1 };
int[] a2 = { 42, 2222, 9 };
for(int i = 0; i < a1.Length; i++)
{
if(a2.Contains(a1[i]))
{
//notice i-- here because iterating array shifted to left
ShiftToLeft(a1, i--+1);
}
}
Console.WriteLine(string.Join(",", a1));
}
private static void ShiftToLeft(int[] array, int fromIndex)
{
Array.Copy(array, fromIndex, array, fromIndex-1, array.Length - fromIndex);
array[array.Length-1] = 0;
}
Try This:
int[] a1 = { 42, 3, 9, 42, 42, 0, 42, 9, 42, 42, 17, 8, 2222, 4, 9, 0, 1 };
int[] a2 = { 42, 2222, 9 };
var result = a1.Where(x => !a2.Contains(x)).Concat(new int[a1.Length]).Take(a1.Length);
Console.WriteLine(String.Join(", ", result));
Related
I have a jagged array with a multidimensional array and want to remove an array inside the multidimensional array. My code is:
int[][,] arr = new int[4][,];
arr[0] = new int[,] {
{ 1, 2, 3 }, // <- I want to remove this row
{ 4, 5, 6 },
{ 5, 6, 7 },
{ 8, 9, 10 } };
arr[1] = new int[,] {
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 },
{ 13, 14, 15, 16 } };
arr[2] = new int[,] {
{ 1, 2, 3, 4, 5 },
{ 5, 6, 7, 8, 9 },
{ 10, 11, 12, 13, 14 },
{ 15, 16, 17, 18, 19 } };
arr[3] = new int[,] {
{ 1, 2, 3, 4, 5, 6},
{ 5, 6, 7, 8, 9, 10},
{ 11, 12, 13, 14, 15, 16 },
{ 17, 18, 19, 20, 21, 22 } };
int[,] removeArray = { { 1, 2, 3 } };
I tried to remove {1, 2, 3} from arr[0] by using Linq:
arr = arr
.Where((val, i) => i != 0)
.ToArray();
but this removes the whole arr[0] row. Does anyone know how I can get to remove {1,2,3} using Linq?
Unlike jagged arrays, multidimensional ones doesn't consist of arrays:
int[][] jagged = new int[][] {
new[] { 1, 2, 3 }, // <- this is an array
new[] { 4, 5 }, // <- this is another array
};
int[,] array2D = new int[,] {
{ 1, 2, 3 }, // <- not an array
{ 4, 5, 6 }, // <- not an array
};
So if you want to "remove" row from 2d array, you have to recreate it; something like this:
private static T[,] RemoveRows<T>(T[,] source, T[] row) {
if (row.Length != source.GetLength(1))
return source;
var keepRows = new List<int>();
for (int r = 0; r < source.GetLength(0); ++r)
for (int c = 0; c < row.Length; ++c)
if (!object.Equals(source[r, c], row[c])) {
keepRows.Add(r);
break;
}
if (keepRows.Count == source.Length)
return source;
T[,] result = new T[keepRows.Count, source.GetLength(1)];
for (int r = 0; r < keepRows.Count; ++r)
for (int c = 0; c < result.GetLength(1); ++c)
result[r, c] = source[keepRows[r], c];
return result;
}
and then
// we remove row; let it be 1d array, not 2d one
int[] removeArray = { 1, 2, 3 };
arr = arr
.Select(array => RemoveRows(array, removeArray))
.ToArray();
please, fiddle yourself
For an example if I want to iterate test and perfrorm operations on elements from that array but they have to be formatted in a particular way.
Essentially I am trying to loop over a 2d array using a 2d array.
double[,] test = {
{9, 8, 7, 6, 5, 4, 3, 2},
{8, 7, 6, 5, 4, 3, 2, 1},
{7, 6, 5, 4, 3, 2, 1, 0},
{6, 5, 4, 3, 2, 1, 0, 0},
{5, 4, 3, 2, 1, 0, 0, 0},
{4, 3, 2, 1, 0, 0, 0, 0},
{3, 2, 1, 0, 0, 0, 0, 0},
{2, 1, 0, 0, 0, 0, 0, 0},
};
double[,] subset = new double[2,2]; //used in math
What I would like to be able to do is to iterate over any size matrix (assuming that they are even sized and square) with each iteration looking like this:
Iteration 1:
subset[0,0] = test[0,0];
subset[0,1] = test[0,1];
subset[1,0] = test[1,0];
subset[1,1] = test[1,1];
So basically it selected a square same size as subset out of the large matrix.
Iteration 2:
subset[0,2] = test[0,2];
subset[1,2] = test[1,2];
subset[0,3] = test[0,3];
subset[1,3] = test[1,3];
You can do this via an extension method. A few things worth mentioning:
Using Array.Copy as opposed to manually assigning the elements should yield better performance.
Like Tom A mentioned in a comment, you should use yield return to create an IEnumerable. You can then iterate over it using a foreach loop, or perform other operations.
Implementation:
static class MatrixExtensions
{
public static IEnumerable<T[,]> ChunkMatrix<T>(this T[,] inputMatrix, int chunkWidth, int chunkHeight)
{
int inputWidth = inputMatrix.GetLength(0);
int inputHeight = inputMatrix.GetLength(1);
for(int i = 0; i < inputWidth; i += chunkWidth)
{
for(int j = 0; j < inputHeight; j += chunkHeight)
{
T[,] chunk = new T[chunkWidth, chunkHeight];
for(int k = 0; k < chunkWidth; k++)
{
int sourceIndex = i*inputWidth + k* inputWidth + j;
var destinationIndex = k* chunkHeight;
Array.Copy(inputMatrix, sourceIndex, chunk, destinationIndex, chunkHeight);
}
yield return chunk;
}
}
}
}
Usage:
double[,] test = {
{1, 2, 3, 4, 5, 6, 7, 8},
{9, 10, 11, 12, 13, 14, 15, 16},
{17, 18, 19, 20, 21, 22, 23, 24},
{25, 26, 27, 28, 29, 30, 31, 32},
{33, 34, 35, 36, 37, 38, 39, 40},
{41, 42, 43, 44, 45, 46, 47, 48},
{49, 50, 51, 52, 53, 54, 55, 56},
{57, 58, 59, 60, 61, 62, 63, 64},
};
foreach(double[,] chunk in test.ChunkMatrix(2, 2))
{
// First iteration:
// 1 2
// 9 10
//
// Second iteration:
// 3 4
// 11 12
//
// ...
}
I changed your test data to not include duplicate values, as to better illustrate the effect.
It should be noted that my implementation will not work correctly on matrices with dimensions that are not multiples of the chunks' dimensions, as it was mentioned in a comment that this will never be the case. If needed, modifying it to account for this scenario shouldn't be too hard.
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
const int COLUMNS = 8;
const int ROWS = 8;
const int SIZE = 2;
static void Main(string[] args)
{
double[,] test = {
{9, 8, 7, 6, 5, 4, 3, 2},
{8, 7, 6, 5, 4, 3, 2, 1},
{7, 6, 5, 4, 3, 2, 1, 0},
{6, 5, 4, 3, 2, 1, 0, 0},
{5, 4, 3, 2, 1, 0, 0, 0},
{4, 3, 2, 1, 0, 0, 0, 0},
{3, 2, 1, 0, 0, 0, 0, 0},
{2, 1, 0, 0, 0, 0, 0, 0},
};
for (int i = 0; i < COLUMNS; i += SIZE)
{
for (int j = 0; j < ROWS; j += SIZE)
{
for (int k = j; k < j + SIZE; k++)
{
for (int l = i; l < i + SIZE; l++)
{
Console.WriteLine("test[{0}, {1}] = {2}", k, l, test[k, l]);
}
}
}
}
Console.ReadLine();
}
}
}
I am not saying this is the best solution but while I look at the yield statement I managed to get it working using this method.
public static double[,] GetMapSection(Rectangle area, double[,] map) {
double[,] result = new double[area.Width, area.Height];
for (Int32 y = 0; y < area.Height; ++y) {
for (Int32 x = 0; x < area.Width; ++x) {
result[x, y] = map[x + area.X, y + area.Y];
}
}
return result;
}
I call it via:
List<double[,]> testChannel = new List<double[,]>();
for (int i = 0; i < Math.Sqrt(large_mapdata.Length); i+=8) {
for (int j = 0; j < Math.Sqrt(large_mapdata.Length); j+=8) {
testChannel.Add(GetMapSection(new Rectangle(i, j, 8, 8), large_mapdata));
}
}
In this example I am creating 8x8 chunks out of an array that is 32x32 in size.
I can confirm that this worked for me and is cleaner than what I had before.
I got 2 int List like below
List<int> list1 = new List<int> { 2, 6, 1, 8, 9, 4, 12, 24, 23, 3, 11, 15 };
List<int> list2 = new List<int> { 6, 9, 4, 12, 24, 23, 5, 16, 18, 2, 7, 14 };
list1 = { 2, 6, 1, 8, 9, 4, 12, 24, 23, 3, 11, 15 };
list2 = { 6, 9, 4, 12, 24, 23, 5, 16, 18, 2, 7, 14, };
When I compare this 2 lists i need to get result in new List like:
{ 9, 4, 12, 24, 23 }
Need fast working solution under 500 ms. Original list contains 35 int items and need to find 5 same like on example above.
I guess the best what you can do is go through the list and see whether you find a good starting index.
for (int i = 0; i <= list1.Count - length; i++)
{
for (int j = 0; j <= list2.Count - length; j++)
{
var match = true;
for (int k = 0; k < length; k++)
{
if (list1[k] != list2[k]) { match = false; break; }
}
if (match)
{
Console.WriteLine("Starting indices are {0} and {1}", i,j);
break;
}
}
}
Edit2: Introduced variable length sublists
Edit: Maybe you can accelerate this solution by prefiltering the indices as you create sums of the 5-element-chunks and intersect these sums. This will need O(n) for creating the sums and O(n) for intersecting them. However, then it is up to your data distribution whether you can find the true substrings in less than O(n^2) but you might be lucky.
Alternatively, you can save the concatenation of the strings separated by e.g. a semicolon and then intersect the strings. This will run deterministal in O(n) but will have a high memory footprint.
Here's a dumb solution that executes for me in less than 0.000 seconds on my machine, and 0.016 seconds on .dotnetfiddle.
public static void Main()
{
List<int> list1 = new List<int> { 2, 6, 1, 8, 9, 4, 12, 24, 23, 3, 11, 15 };
List<int> list2 = new List<int> { 6, 9, 4, 12, 24, 23, 5, 16, 18, 2, 7, 14 };
CommonSublist(5, list1, list2).Dump();
}
private static List<int> CommonSublist(int length, List<int> list1, List<int> list2) {
for (int i=0;i<list1.Count-length;i++) {
for (int j=0;j<list2.Count-length;j++) {
List<int> output = new List<int>();
for (int k=0;k<length;k++) {
if (list1[i+k]==list2[j+k]) {
output.Add(list1[i+k]);
}
else {
break;
}
}
if (output.Count == length) {
return output;
}
}
}
return null;
}
I am trying to determine what the neighbour bets would be for a given number on a roulette wheel.
At the moment I pass a pocket number to a function and below is my code. "pocket_number()[0]" is the value of the number I want to determine the neighbours of.
int[] neightbourbets = neighbourbets(pocket_number()[0]);
neighbourbets() is as follows (this outputs an array of element numbers so elsewhere in my program I can extract them from the same array structure). At the moment I have a crude way of determining the the neighbour bets and getting the function to state which numbers are 6 numbers either side of it.
Is there a better way to do this? I've found one of the problems (that I've overcome with the below) is if I want to know the neighbours for "0" for example which means the code needs to get the numbers from the end of the array.
public int[] neighbourbets(int x)
{
int[] pocket_array = new[] {0, 32, 15, 19, 4, 21, 2, 25, 17, 34, 6, 27, 13, 36, 11, 30, 8, 23, 10, 5, 24, 16, 33, 1, 20, 14, 31, 9, 22, 18, 29, 7, 28, 12, 35, 3, 26};
int predictednum = Array.IndexOf(pocket_array,x); //element number of pocket_array for chosen number
int[] neighbourbets = new[] {0,0,0,0,0,0,0,0,0,0,0,0,0};
neighbourbets[0] = predictednum;
neighbourbets[1] = predictednum+1;
neighbourbets[2] = predictednum+2;
neighbourbets[3] = predictednum+3;
neighbourbets[4] = predictednum+4;
neighbourbets[5] = predictednum+5;
neighbourbets[6] = predictednum+6;
neighbourbets[7] = predictednum-1;
neighbourbets[8] = predictednum-2;
neighbourbets[9] = predictednum-3;
neighbourbets[10] = predictednum-4;
neighbourbets[11] = predictednum-5;
neighbourbets[12] = predictednum-6;
for (int i = 0; i < neighbourbets.Length; i++)
{
//clockwise neighours
if (neighbourbets[i] == -1) {
neighbourbets[i] = 36;
}
if (neighbourbets[i] == -2) {
neighbourbets[i] = 35;
}
if (neighbourbets[i] == -3) {
neighbourbets[i] = 34;
}
if (neighbourbets[i] == -4) {
neighbourbets[i] = 33;
}
if (neighbourbets[i] == -5) {
neighbourbets[i] = 32;
}
if (neighbourbets[i] == -6) {
neighbourbets[i] = 31;
}
//anticlockwise neighbours
if (neighbourbets[i] == 37) {
neighbourbets[i] = 0;
}
if (neighbourbets[i] == 38) {
neighbourbets[i] = 1;
}
if (neighbourbets[i] == 39) {
neighbourbets[i] = 2;
}
if (neighbourbets[i] == 40) {
neighbourbets[i] = 3;
}
if (neighbourbets[i] == 41) {
neighbourbets[i] = 4;
}
if (neighbourbets[i] == 42) {
neighbourbets[i] = 5;
}
}
return neighbourbets;
}
Any helps or guidence is appreciated! :)
Write a small helper function to wrap around the index:
private int GetPocketIndex( int start, int offset, int count )
{
int pos = ( start + offset ) % count;
if( pos >= 0 )
return pos;
else
return count + pos; // pos is negative so we use +
}
The modulus there will help it wrap around when it goes above the maximum, and the if will do it for the minimum. This could probably be done easier though, but it eludes me at the moment.
Then, if you need that specific order, perhaps something like this:
int[] offsets = new int[] { 0,
1, 2, 3, 4, 5, 6,
-1, -2, -3, -4, -5, -6 };
int[] neighbourbets = new int[offsets.Length];
for( int i = 0; i < offsets.Length; i++ )
neighbourbets[i] = GetPocketIndex( predictednum, offsets[i], pocket_array.Length );
Or, if any order will do:
int count = 6;
int[] neighbourbets = new int[count * 2 + 1];
for( int i = 0; i < neighbourbets.Length; i++ )
neightbourbets[i] = GetPocketIndex( predictednum, i - count, pocket_array.Length );
The following would give you the result with the x in the middle of the result array and the neighbours to the left and right of it:
public static int[] neighbourbets2(int x, int neighborCount)
{
int[] pocket_array = new[] { 0, 32, 15, 19, 4, 21, 2, 25, 17, 34, 6, 27, 13, 36, 11, 30, 8, 23, 10, 5, 24, 16, 33, 1, 20, 14, 31, 9, 22, 18, 29, 7, 28, 12, 35, 3, 26 };
int predictednum = Array.IndexOf(pocket_array, x);
// Initialize the result array. Its size is double the neighbour count + 1 for x
int[] result = new int[neighborCount * 2 + 1];
// Calc the start index. We begin at the most left item.
int startAt = predictednum - neighborCount;
// i - position in the result array
// j - position in the pocket_array
for (int i = 0, j = startAt; i < result.Length; i++, j++)
{
// Adjust j if it's less then 0 to wrap around the array.
result[i] = pocket_array[j < 0 ? j + pocket_array.Length : j];
// If we are at the end then start from the beginning.
if (j == pocket_array.Length)
{
j = 0;
}
}
return result;
}
int[] a = {120, 60, 50, 40, 30, 20};
int[] b = {12, 29, 37, 85, 63, 11};
int[] c = {30, 23, 90 ,110, 21, 34};
Now i want to sort a and use its index to sort b and c
For eg:
sorted a = {20,30,40,50,60,120};
sorted b should be ={ 11,63,85,37,29,12};
and sorted c should be = { 34,21,110,90,23,30};
How to do it in C#
One option:
int[] a = {120, 60, 50, 40, 30, 20};
int[] b = {12, 29, 37, 85, 63, 11};
int[] c = {30, 23, 90 ,110, 21, 34};
var ordered = a.Select((item, index) =>
Tuple.Create(item, b[index], c[index]))
.OrderBy(tuple => tuple.Item1).ToArray();
a = ordered.Select(tuple => tuple.Item1).ToArray();
b = ordered.Select(tuple => tuple.Item2).ToArray();
c = ordered.Select(tuple => tuple.Item3).ToArray();
You could do it with a layer of indirection, like this:
Put the values 0, 1, 2, ..., N-1 into an int array, named indices, say.
Sort the array indices such that a[indices[i]] <= a[indices[i+1]] for all i. Your compare function will compare a[indices[Left]] with a[indices[Right]].
Access elements in the other arrays using the indirection: a[indices[i]] and so on.
You could make new copies of a, b and c if you wish, using the order defined by indicies. But you also have the option of not modifying the original arrays.
This option of not modifying the original arrays is quite interesting. It allows you have have multiple simultaneous orderings active in tandem.
Got bored so I tried to minimise the creation of new objects and sorting.
static void Main(string[] args)
{
int[] a = { 120, 60, 50, 40, 30, 20 };
int[] b = { 12, 29, 37, 85, 63, 11 };
int[] c = { 30, 23, 90, 110, 21, 34 };
var indexes = Enumerable.Range(0, a.Length).OrderBy(i => a[i]).ToArray();
var temp = new int[a.Length];
foreach (var arr in new[] { a, b, c })
{
for (int i = 0; i < a.Length; i++) temp[i] = arr[indexes[i]];
for (int i = 0; i < a.Length; i++) arr[i] = temp[i];
}
Console.WriteLine(String.Join(", ", a));
Console.WriteLine(String.Join(", ", b));
Console.WriteLine(String.Join(", ", c));
Console.ReadLine();
}
Not the best it could be (I'm sure you can get rid of the temp array somehow) - but a different solution nonetheless. I'd support sticking with the LINQesque solutions until performance becomes an issue.
You can use SortedList for this. SortedList sorts your items using a Key. Also it allows you
to add new items to your collection.
SortedList Class:
Represents a collection of key/value pairs that are sorted by the keys and are accessible by key and by index.
SortedList by MSDN
I suggest to use LINQ as Eli Arbel provided the answer.
But here is an other solution for those who don't know LINQ.
class Program
{
public static int get_key(int key , int [,] keylist)
{
for (int i = 0; i <= keylist.GetUpperBound(0); ++i)
{
if (keylist[i, 0] == key)
return keylist[i, 1];
}
return -1;
}
public static int[] Sort_by_index(int [] arr , int [] key , int [,] index_list)
{
int[] _out = new int[arr.Length];
for (int i = 0; i < key.Length; i++)
{
//Get key index
int key_index = get_key(key[i], index_list);
_out[i] = arr[key_index];
}
return _out;
}
static void Main(string[] args)
{
int[] a = { 120, 60, 50, 40, 30, 20 };
int[] b = { 12, 29, 37, 85, 63, 11 };
int[] c = { 30, 23, 90, 110, 21, 34 };
int[,] a_index = { { 120, 0 }, { 60, 1 }, { 50, 2 }, { 40, 3 }, { 30, 4 }, { 20, 5 } };
Array.Sort(a);
b =Sort_by_index(b, a, a_index);
c =Sort_by_index(c, a, a_index);
Console.WriteLine("Result A");
Console.WriteLine(string.Join(", ",a));
Console.WriteLine("Result B");
Console.WriteLine(string.Join(", ",b));
Console.WriteLine("Result C");
Console.WriteLine(string.Join(", ",c));
Console.ReadKey(false);
}
}