remove a value from an int array c# - c#

I have an array of int values int[] ids.
I have a Datatable DataTable dt
I want to keep only those values in the array that are there in the Datatable column ids
Say int[] ids contain [2,3,4,5]
dt contains [2,3,4,3,4] ---ids here may repeat
so output ids will have only [2,3,4]
Pls suggest ways with lambda or linq....
I tried the crude way using two foreachs.

use
int[] myIDs = (from d in dt.AsEnumerable() select d.Field<int>("id")).Intersect (ids).ToArray();
For reference see:
http://msdn.microsoft.com/en-us/library/bb360891.aspx
http://msdn.microsoft.com/en-us/library/system.data.datatableextensions.asenumerable.aspx
http://msdn.microsoft.com/en-us/library/bb460136.aspx
http://msdn.microsoft.com/en-us/library/x303t819.aspx
http://msdn.microsoft.com/en-us/vcsharp/aa336746
http://msdn.microsoft.com/en-us/vcsharp/aa336761.aspx#intersect1

You need to create a new array.
Arrays are fixed size.
If you want a data structure able to remove an element you need a List.
Note that List removal operation have a worst case complexity of O(n).
For your particular problem however i would write something like this:
public int[] MyFunc(DataTable dt, int[] array)
{
Set<int> allowedsIds = new Set<int>();
Fill your set with ids you want to keep
int[] newArray = new int[inputArray.Length];
int newArrayCount = 0;
for (int i = 0; i < inputArray.Length; ++i)
{
if (allowedsIds.Contains(inputArray[i]))
{
newArray[newArrayCount++] = inputArray[i];
}
}
Array.Resize(ref newArray, newArrayCount);
return newArray;
}

You need the intersection of the 2 collections. Linq as a Intersect method for that.
From the Linq 101 samples:
public void Linq50()
{
int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 };
int[] numbersB = { 1, 3, 5, 7, 8 };
var commonNumbers = numbersA.Intersect(numbersB);
Console.WriteLine("Common numbers shared by both arrays:");
foreach (var n in commonNumbers)
{
Console.WriteLine(n);
}
}
You can find more examples here in Linq 101 Samples.

Use the Intersect function:
var ids = new[] {2, 3, 4, 5};
var dt = new[] {2, 3, 4, 3, 4};
foreach (var id in ids.Intersect(dt))
{
}

You could create List<int> fromDB and (cycling over dataset) fill it with ids column values.
Then you could use:
List<int> result = ids.Intersect(fromDB).ToList();

Related

Check if an array sorted in ascending order is contained within another array?

If I have a list,
int[] ints = { 4, 2, 6, 5 };
and I sort the list using Array.Sort(ints), and I've got another array,
int[] i = { 1, 2, 4, 5, 6, 8, 12 };
how do I check that the sorted array, ints is contained within i?
If the array has extra elements,
int[] ints = { 4, 2, 6, 3, 5 };
that are not part of i then this should return false, unlike with this solution:
Here is a Linq solution that should give you what you need:
names.Any(x => subnames.Contains(x))
This gives your desired result:
int firstIndex = Array.IndexOf(i, ints.First());
bool sameSequenceContained = firstIndex != -1
&& i.Skip(firstIndex).Take(ints.Length).SequenceEqual(ints);
So first check if the first integer is contained at all, then use it's index to get the sub-sequence with Skip and Take, then use SequenceEqual to check if it's the same sequence.
Edit: i think it's not that easy since it's possible that there are more than one index of the first item. You could use such an extension method to find all:
public static class Extensions
{
public static IEnumerable<int> EnumerateAllIndex<T>(this IEnumerable<T> sequence, T item, IEqualityComparer<T> comparer = null)
{
if (comparer == null)
{
comparer = EqualityComparer<T>.Default;
}
int index = 0;
foreach(T itemInSequence in sequence)
{
if(comparer.Equals(item, itemInSequence))
{
yield return index;
}
index++;
}
}
}
Now you are able to use this readable and efficient query:
bool sameSequenceContained = i.EnumerateAllIndex(ints.First())
.Any(index => i.Skip(index).Take(ints.Length).SequenceEqual(ints));
I guess, you can use this linq expression.
ints.All(num => i.Contains(num));
Here's the full code.
int[] ints = {4, 2, 6, 5};
Array.Sort(ints);
int[] i = {1, 2, 4, 5, 6, 8, 12};
bool IsPartOf(int[] ints, int[] i)
{
return ints.All(num => i.Contains(num));
}
Console.WriteLine(IsPartOf(ints, i));

Summing up a list of integer arrays using threads for each array in C# Console application

I have a List of int arrays. The list can be from 1 to 4 arrays.
I want to know how do i go about summing each array with individual threads and
placing the summed values into a new int array.
If the order of the new array is not important here you have a example
List<int[]> arraysList = new List<int[]>();
arraysList.Add(new int[] { 2, 3, 5 });
arraysList.Add(new int[] { 2, 3, 5, 9, 123, 5 });
arraysList.Add(new int[] { 3 });
arraysList.Add(new int[] { 9,8 });
ConcurrentBag<int> SummedValueOfEveryArray = new ConcurrentBag<int>();
Parallel.ForEach(arraysList, array =>
{
SummedValueOfEveryArray.Add(array.Sum());
});
//Your result
var result = SummedValueOfEveryArray.ToArray<int>();
//The sum of all arrays
var totalSum = SummedValueOfEveryArray.Sum();
This code will do what you ask. One side note however, this only parallelizes when .Net feels it could improve performance.
List<int[]> intlist = new List<int[]>();
int[] result = intlist.AsParallel().Select(arr => arr.Sum()).ToArray();
Given 1 to 4 arrays it may be that .Net never sees the point of parallelizing. But if you absolutely must you can force parallelization by using Parallel.For as shown below.
List<int[]> intlist = new List<int[]>();
int[] result = new int[intlist.Count];
Parallel.For(0, intlist.Count, i =>
{
result[i] = intlist[i].Sum();
});

How to access and re-format Jagged Array in C#

I have 2D array in c#, like this:
int[][] 2darray = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
how can I get one column as normal array, like
int[] array = 2darray[1][]; //example, not working
and have
int[] array = {3,4};
?
Thanks.
There are several reasons why your code can't compile
This way it works:
int[][] array2d = { new[]{ 1, 2 }, new[]{ 3, 4 }, new[]{ 5, 6 }, new[]{ 7, 8 } };
int[] array = array2d[0];
Problems:
2darray is not a valid variable name
The indexing is wrong
The initialization of the original array is wrong
EDIT:
As stated by #heltonbiker, if you require all elements of the first column, you can use this:
int[] col = array2d.Select(row => row[0]).ToArray();
For an array with two columns and four rows, you can use LINQ this way:
using System.Linq;
first_column = _2darray.Select(row => row[0]).ToArray();
Note that changing the first or second array will not change the other one.
You are confusing jagged arrays and multidimensional arrays in C#. While they are similar, there is a slight difference. Rows in a jagged array can have a different number of elements, while in a 2D-array they are of the same length. Therefore when working with jagged arrays you need to remember to write handling for a missing column element. I composed a sample console app below to show how both of them work - it uses 0 as a substitute for a missing element, but you can throw an error etc.:
using System.Collections.Generic;
namespace JaggedArrayExample
{
class Program
{
static void Main(string[] args)
{
//jagged array declaration
int[][] array1;
//jagged array declaration and assignment
var array2 = new int[][] {
new int[] { 1, 2 },
new int[] { 3, 4 },
new int[] { 5, 6 },
new int[] { 7, 8 }
};
//2D-array declaration
int[,] array3;
//2D-array declaration and assignment (implicit bounds)
var array4 = new int[,] {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
//2D-array declaration and assignment (explicit bounds)
var array5 = new int[4, 2] {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
//get rows and columns at index
var r = GetRow(array2, 1); //second row {3,4}
var c = GetColumn(array2, 1); //second column {2,4,6,8}
}
private static int[] GetRow(int[][] array, int index)
{
return array[index]; //retrieving the row is simple
}
private static int[] GetColumn(int[][] array, int index)
{
//but things get more interesting with columns
//especially if jagged arrays are involved
var retValue = new List<int>();
foreach (int[] r in array)
{
int ub = r.GetUpperBound(0);
if (ub >= index) //index within bounds
{
retValue.Add(r[index]);
}
else //index outside of bounds
{
retValue.Add(0); //default value?
//or you can throw an error
}
}
return retValue.ToArray();
}
}
}
try this, it should work
int[] array = array2d[1];
Change the name of the variable to array2d, you cannot have variable that starts with number, a variable can start with letter or underscore.

Merging arrays with common element

I want to merge arrays with common element. I have list of arrays like this:
List<int[]> arrList = new List<int[]>
{
new int[] { 1, 2 },
new int[] { 3, 4, 5 },
new int[] { 2, 7 },
new int[] { 8, 9 },
new int[] { 10, 11, 12 },
new int[] { 3, 9, 13 }
};
and I would like to merge these arrays like this:
List<int[]> arrList2 = new List<int[]>
{
new int[] { 1, 2, 7 },
new int[] { 10, 11, 12 },
new int[] { 3, 4, 5, 8, 9, 13 } //order of elements doesn't matter
};
How to do it?
Let each number be a vertex in the labelled graph. For each array connect vertices pointed by the numbers in the given array. E.g. given array (1, 5, 3) create two edges (1, 5) and (5, 3). Then find all the connected components in the graph (see: http://en.wikipedia.org/wiki/Connected_component_(graph_theory))
I'm pretty sure it is not the best and the fastest solution, but works.
static List<List<int>> Merge(List<List<int>> source)
{
var merged = 0;
do
{
merged = 0;
var results = new List<List<int>>();
foreach (var l in source)
{
var i = results.FirstOrDefault(x => x.Intersect(l).Any());
if (i != null)
{
i.AddRange(l);
merged++;
}
else
{
results.Add(l.ToList());
}
}
source = results.Select(x => x.Distinct().ToList()).ToList();
}
while (merged > 0);
return source;
}
I've used List<List<int>> instead of List<int[]> to get AddRange method available.
Usage:
var results = Merge(arrList.Select(x => x.ToList()).ToList());
// to get List<int[]> instead of List<List<int>>
var array = results.Select(x => x.ToArray()).ToList();
Use Disjoint-Set Forest data structure. The data structure supports three operations:
MakeSet(item) - creates a new set with a single item
Find(item) - Given an item, look up a set.
Union(item1, item2) - Given two items, connects together the sets to which they belong.
You can go through each array, and call Union on its first element and each element that you find after it. Once you are done with all arrays in the list, you will be able to retrieve the individual sets by going through all the numbers again, and calling Find(item) on them. Numbers the Find on which produce the same set should be put into the same array.
This approach finishes the merge in O(α(n)) amortized (α grows very slowly, so for all practical purposes it can be considered a small constant).

condition in function parameter

I'm new in C#. I would like to check some condition in function parameter.
I have to write function which in their parameter will check which numbers are greater than zero and return this numbers. How to solve it?
I have tried in many ways but none work.
Below is the code I have:
int[] arr = new int[] {2, 3, -5};
List<int> returnGreaterThanZero(int[] numbers)
{
List<int> greaterList = new List<int>();
foreach (int oneNum in numbers)
{
if (oneNum > 0)
greaterList.Add(oneNum);
}
return greaterList;
// return greaterList.ToArray(); // if you want to return int[] instead of List<int>
}
Of course you can use linq instead of foreach too.
On top
using System.Linq;
In your code
int[] arr = new int[] { 2, 3, -5 };
var result = arr.Where(x => x > 0).ToList();
This is how you do it using linq.
If you want greater than an arbitrary number then you can do Where(x=>x > someNumber) and pass someNumber in as a parameter elsewhere.

Categories