I have a list of integers that I would like to search for a sequence.
For example, if I have a master list:
1, 2, 3, 4, 9, 2, 39, 482, 19283, 19, 23, 1, 29
And I want to find sequence:
1, 2, 3, 4
I would like some easy way to fill a subset list with:
1, 2, 3, 4 + the next five integers in the master list
And then remove the integers in the subset list from the master list so at the end of the operation, my lists would look like this:
Master list:
19, 23, 1, 29
Subset list:
1, 2, 3, 4, 9, 2, 39, 482, 19283
Hope that makes sense. I'm guessing maybe LINQ would be good for something like this, but I've never used it before. Can anyone help?
You could start with writing a function IndexOfSublist that can find a sublist inside a list. This has been asked many times before.
Assuming you have implemented IndexOfSublist, use it to find the first element of your result, then you could use GetRange to select the elements that you want to keep and then RemoveRange to remove the elements from the original list.
List<int> l = new List<int> { 1, 1, 2, 3, 4, 9, 2, 39, 482, 19283, 19, 23, 1, 29 };
List<int> needle = new List<int> { 1, 2, 3, 4 };
int i = indexOfSubList(l, needle);
if (i != -1)
{
// TODO: What should we do if there are fewer than four
// elements left after the needle? Currently we just throw.
List<int> result = l.GetRange(i, needle.Count + 4);
l.RemoveRange(i, result.Count);
// TODO: Do something with the result;
}
HINT
you can try something like this along with an iterator:
List<int> n = new List<int>() { 1, 2, 3, 4, 9, 2, 39, 482, 19283, 19, 23, 1, 29 };
List<int> toFind = new List<int>() { 1, 2, 3, 4 };
if (n.Skip(indextostart).Take(4).ToList()==toFind)
{
n.RemoveRange(indextostart,4);
}
Related
Sorry if the title's worded a bit weird but this is what I'm trying to get to.
Lets say you have an array of integers like this:
int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
What would be the best way to use this array to return a new array but with the values of each pair summed together, so using the array above, it would return
{ 3, 7, 11, 15, 19 }
Obviously you can so something basic like
int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var x = new List<int>();
for (int i=0;i<arr.Length;i+=2)
x.Add(arr[i] + arr[i+1]);
But if you want to keep your code concise and/or work with different items, this doesn't really seem like the best option.
So is there any other/better way to do this? I was testing some ideas with Enumerable.Aggregate but couldn't come up with anything, please share ideas.
I would argue that your approach is perfectly fine, but for LINQ you can do some stuff with Chunk:
var x = arr
.Chunk(2)
.Where(c => c.Length == 2)
.Select(c => c.Sum())
.ToArray();
Well, your code is readable and efficien; however, you can generalize your current solution a bit:
Last array item(s) can well have no pair
We can combine not only pairs, but three or four items etc.
If you are looking for such kind of code for
int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
the modifiction of your solution can be:
const int size = 2;
int[] result = new int[arr.Length / size + Math.Sign(arr.Length % size)];
for (int i = 0; i < arr.Length; ++i)
result[i / size] += arr[i];
For instance, if we set size = 3; then for we'll get { 6, 15, 24, 10 } as the result. Note, that the last group is incomplete:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
| | | | | | ||
6 15 24 10
I have a list of integer list like -
List<List<int>> dataList = new List<List<int>> {
new List<int>{ 0, 2, 4, 7 },
new List<int>{ 1, 6, 3 },
new List<int>{ 2, 0, 7, 9 },
new List<int>{ 3, 1, 6 },
new List<int>{ 4, 0, 2 },
new List<int>{ 5, 2, 7 },
};
I want to merge all the list those have duplicates and generate a list of integer list where no values should be common in any list.
The output should be like--
0, 2, 4, 5, 7, 9
1, 3, 6
If you want one single list, then you can do this:
// flatten your list:
var newList = new List<int>();
foreach (var list in output) {
newList.AddRange(list);
}
// make sure every number is only once in that list:
newList.Distinct() // here is linq!
var output = new List<List<int>>();
output.Add(newList);
I have two arrays, one with values an one with indices
int[] items = { 1, 2, 3, 7, 8, 9, 13, 16, 19, 23, 25, 26, 29, 31, 35, 36, 39, 45 };
int[] indices = { 1, 3, 5, 6, 7, 9 };
now I want a result array from the items selected by the indices of indices array
// 2, 7, 9, 13, 19
int[] result = new []{ items[1], items[3], items[5], items[6], items[7], items[9] };
Question: Is there a more generic approach for this?
var results = Array.ConvertAll(indices, i => items[i]);
Try using Linq:
int[] items = { 1, 2, 3, 7, 8, 9, 13, 16, 19, 23, 25, 26, 29, 31, 35, 36, 39, 45 };
int[] indices = { 1, 3, 5, 6, 7, 9 };
int[] result = indices
.Select(index => items[index])
.ToArray();
A good old for loop should be able to do this job as well:
int[] items = { 1, 2, 3, 7, 8, 9, 13, 16, 19, 23, 25, 26, 29, 31, 35, 36, 39, 45 };
int[] indices = { 1, 3, 5, 6, 7, 9 };
List<int> resultList = new List<int>();
for (int i = 0; i < indices.Length; i++)
{
resultList .Add(items[indices[i]]);
}
Explanation:
when using the [ ] operator to access a specific index in indices it will return the number. This can again be used to index/access a specific location in items. So you have a double indexing.
EDIT:
If you need the result as an array you can use the ToArray method to convert it:
int [] result = resultList.ToArray();
For the sake of alternative:
int[] result = items.Select((value, index) => new { Index = index, Value = value }) //Add indexes
.Where(w => indices.Contains(w.Index)) //Filter by indexes
.Select(s => s.Value).ToArray(); //Extract values to result array
I have a jagged array in a c# program that is declared where column one represents a year, column two represents the number of a month (1-12) and column three represents some data for that month:
double[][] data = new double[3][]
{
new double[] {1930,1931,1931,1931,1931,1931,1931,1931,1931,1931,1931,1931,1931,1932,1932,1932,1932,1932,1932,1932,1932,1932,1932,1932,1932},
new double[] {12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
new double[] {5, 6, 8, 3, 5, 8, 9, 6, 5, 6, 7, 5, 3, 2, 2, 2, 5, 7, 8, 3, 2, 2, 1, 2, 5}
};
As you can see, the first array is ordered. I would like to know how I could sort the jagged array by the second column , in ascending order like this.
{1931,1932,1931,1932,1931,1932,1931,1932,1931,1932,1931,1932,1931,1932,1931,1932,1931,1932,1931,1932,1931,1932,1930,1931,1932}
{1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12}
etc...
My question is, how would I be able to implement this using an insertion sort. It needs to be a custom algorithm and cannot make use of the Array.Sort algorithm that comes as part of C#
Thanks
The insertion sort algorithm can easily be generalized (abstracted) to work on indexes by defining two functions - one to compare two indexes and one to swap two indexes, like this:
public static class Algorithms
{
public static void InsertionSort(int start, int count, Func<int, int, int> compare, Action<int, int> swap)
{
for (int i = start + 1, end = start + count; i < end; i++)
for (int j = i; j > start && compare(j - 1, j) > 0; j--)
swap(j - 1, j);
}
}
Now you can achieve your goal by comparing second columns and swap all columns like this:
Algorithms.InsertionSort(0, data[1].Length,
(a, b) => data[1][a].CompareTo(data[1][b]),
(a, b) => { foreach (var col in data) Algorithms.Swap(ref col[a], ref col[b]); });
where Algorithms.Swap is another little helper:
public static void Swap<T>(ref T a, ref T b) { T c = a; a = b; b = c; }
I am trying to find position in a List based on where LINQ statement and get that item and next (x) amount. Example code:
List<int> numbers = new List<int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
numbers = numbers.Where(elt => elt == 6).Take(3).ToList();
I am trying to get back a filtered list of 6,7,8. However this is not working. Am I approaching this wrong?
Thanks in advance!
You almost got it. You just need to change the Where to a SkipWhile:
numbers = numbers.SkipWhile(elt => elt != 6).Take(3).ToList();
You have to use Where() overload that takes index of item as well and then use with indexOf():
List<int> numbers = new List<int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
var result = numbers.Where((x, i) => i >= numbers.IndexOf(6)).Take(3);
Here's another approach which comes into play when it's possible that the number is not unique and you want all occurences including the two next followers:
List<int> numbers = new List<int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 6, 7, 8, 9, 6 });
numbers = Enumerable.Range(0, numbers.Count)
.Where(index => numbers[index] == 6)
.SelectMany(index => numbers.Skip(index).Take(3))
.ToList(); // 6,7,8,6,7,8,6