Check if there are no repeats in the list - c#

I have a list called com, which contains a bunch of integers. I need to check the list to make sure that each integer only exists once in the list.
So if:
com{1,2,3,4,1,3}
I need have some code to check that 1 is represented twice as well as 3.
This is my best guess on how to solve it:
for (int j = 0; j < com.Count; j++)
{
if (com.Contains(com[j]))
{
lion += 1;
}
else
{
lion = 0;
}
}
But it doesn't work. Can anybody out there help me??

Here's a simple, but probably not that efficient way using LINQ:
using System.Linq;
...
bool containsRepeats = com.Count() != com.Distinct().Count();

You can determine if a collection contains a duplicate by adding each item to a HashSet<T>. The HashSet<T>.Add Method returns false if the item is already present:
public static bool HasDuplicate<T>(this IEnumerable<T> source)
{
var h = new HashSet<int>();
return source.Any(x => !h.Add(x));
}
If you just want to remove all duplicates from the collection, you can use the Enumerable.Distinct Extension Method:
var result = new[] { 1, 2, 3, 4, 1, 3 }.Distinct();
// result == { 1, 2, 3, 4 }

you can try like this..
int[] listOfItems = new[] { 4, 2, 3, 1, 6, 4, 3 };
var duplicates = listOfItems
.GroupBy(i => i)
.Where(g => g.Count() > 1)
.Select(g => g.Key);
foreach (var d in duplicates)
Console.WriteLine(d);

here is for methods to do so:
public static bool LinqAny<T>(IEnumerable<T> enumerable)
{
HashSet<T> set = new();
return enumerable.Any(element => !set.Add(element));
}
public static bool LinqAll<T>(IEnumerable<T> enumerable)
{
HashSet<T> set = new();
return !enumerable.All(set.Add);
}
public static bool LinqDistinct<T>(IEnumerable<T> enumerable)
{
return enumerable.Distinct().Count() != enumerable.Count();
}
public static bool ToHashSet<T>(IEnumerable<T> enumerable)
{
return enumerable.ToHashSet().Count != enumerable.Count();
}

Related

Split a List<int> into groups of consecutive numbers [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I have a sorted List<int> like { 1, 2, 3, 4, 6, 7, 9 }
I want to split that into some groups -- every group has consecutive number like this: { {1, 2, 3, 4}, {6, 7}, {9} }
I know I can use for loop to traverse the list, and compare between the current value and previous value, then decide whether append to last group or create a new group. But I want to find a "pretty" way to do it. Maybe use LINQ?
Edit:
I found a python code from project more-itertools:
def consecutive_groups(iterable, ordering=lambda x: x):
for k, g in groupby(
enumerate(iterable), key=lambda x: x[0] - ordering(x[1])
):
yield map(itemgetter(1), g)
Here is an extension method taken from http://bugsquash.blogspot.com/2010/01/grouping-consecutive-integers-in-c.html
public static IEnumerable<IEnumerable<int>> GroupConsecutive(this IEnumerable<int> list) {
var group = new List<int>();
foreach (var i in list) {
if (group.Count == 0 || i - group[group.Count - 1] <= 1)
group.Add(i);
else {
yield return group;
group = new List<int> {i};
}
}
yield return group;
}
You can use it like this:
var numbers = new[] { 1, 2, 3, 4, 6, 7, 9 };
var groups = numbers.GroupConsecutive();
Once C# 7 is released, this can made even more efficient with the use of Span to avoid creating new lists.
This updated version does it without allocating any lists.
public static class EnumerableExtensions
{
public static IEnumerable<IEnumerable<int>> GroupConsecutive(this IEnumerable<int> list)
{
if (list.Any())
{
var count = 1;
var startNumber = list.First();
int last = startNumber;
foreach (var i in list.Skip(1))
{
if (i < last)
{
throw new ArgumentException($"List is not sorted.", nameof(list));
}
if (i - last == 1)
count += 1;
else
{
yield return Enumerable.Range(startNumber, count);
startNumber = i;
count = 1;
}
last = i;
}
yield return Enumerable.Range(startNumber, count);
}
}
}
Here is my suggestion for an extension method using iterators:
public static IEnumerable<IEnumerable<int>> GroupConsecutive(this IEnumerable<int> src) {
var more = false; // compiler can't figure out more is assigned before use
IEnumerable<int> ConsecutiveSequence(IEnumerator<int> csi) {
int prevCurrent;
do
yield return (prevCurrent = csi.Current);
while ((more = csi.MoveNext()) && csi.Current-prevCurrent == 1);
}
var si = src.GetEnumerator();
if (si.MoveNext()) {
do
// have to process to compute outside level
yield return ConsecutiveSequence(si).ToList();
while (more);
}
}
I must say the Python algorithm is very impressive, here is a C# implementation of it:
public static IEnumerable<IEnumerable<int>> GroupConsecutive(this IEnumerable<int> iterable, Func<int,int> ordering = null) {
ordering = ordering ?? (n => n);
foreach (var tg in iterable
.Select((e, i) => (e, i))
.GroupBy(t => t.i - ordering(t.e)))
yield return tg.Select(t => t.e);
}
Here is a C# one-line implementation of the Python algorithm:
public static IEnumerable<IEnumerable<int>> GroupConsecutive(this IEnumerable<int> iterable, Func<int,int> ordering = null) =>
iterable
.Select((e, i) => (e, i))
.GroupBy(
t => t.i - (ordering ?? (n => n))(t.e),
(k,tg) => tg.Select(t => t.e));
NOTE: C# 8 with nullable annotation context enabled should use Func<int,int>? in both Python methods. You could also use ??= to assign ordering.
The correct implementation of #Bradley Uffner and #NetMage non allocating iterator method is like this:
public static IEnumerable<IEnumerable<int>> GroupConsecutive(this IEnumerable<int> source)
{
using (var e = source.GetEnumerator())
{
for (bool more = e.MoveNext(); more; )
{
int first = e.Current, last = first, next;
while ((more = e.MoveNext()) && (next = e.Current) > last && next - last == 1)
last = next;
yield return Enumerable.Range(first, last - first + 1);
}
}
}
It works correctly even for unordered input, iterates the source sequence only once and handles correctly all corner cases and integer over/underflow. The only case it fails is for consecutive range count bigger than int.MaxValue.
But looking at your follow up question, probably the following implementation will better suit your needs:
public static IEnumerable<(int First, int Last)> ConsecutiveRanges(this IEnumerable<int> source)
{
using (var e = source.GetEnumerator())
{
for (bool more = e.MoveNext(); more;)
{
int first = e.Current, last = first, next;
while ((more = e.MoveNext()) && (next = e.Current) > last && next - last == 1)
last = next;
yield return (first, last);
}
}
}
Try the following code;
public static IEnumerable<IEnumerable<int>> GroupConsecutive(this IEnumerable<int> source)
{
if (!source.Any()) { yield break;}
var prev = source.First();
var grouped = new List<int>(){ prev };
source = source.Skip(1);
while (source.Any())
{
var current = source.First();
if (current - prev != 1)
{
yield return grouped;
grouped = new List<int>();
}
grouped.Add(current);
source = source.Skip(1);
prev = current;
}
yield return grouped;
}
var numbers = new[] { 1, 2, 3, 4, 6, 7, 9 };
var result = numbers.GroupConsecutive();
Output
1,2,3,4
6,7
9

Use Linq to break a list by special values?

I'm trying to use Linq to convert IEnumerable<int> to IEnumerable<List<int>> - the input stream will be separated by special value 0.
IEnumerable<List<int>> Parse(IEnumerable<int> l)
{
l.Select(x => {
.....; //?
return new List<int>();
});
}
var l = new List<int> {0,1,3,5,0,3,4,0,1,4,0};
Parse(l) // returns {{1,3,5}, {3, 4}, {1,4}}
How to implement it using Linq instead of imperative looping?
Or is Linq not good for this requirement because the logic depends on the order of the input stream?
Simple loop would be good option.
Alternatives:
Enumerable.Aggregate and start new list on 0
Write own extension similar to Create batches in linq or Use LINQ to group a sequence of numbers with no gaps
Aggregate sample
var result = list.Aggregate(new List<List<int>>(),
(sum,current) => {
if(current == 0)
sum.Add(new List<int>());
else
sum.Last().Add(current);
return sum;
});
Note: this is only sample of the approach working for given very friendly input like {0,1,2,0,3,4}.
One can even make aggregation into immutable lists but that will look insane with basic .Net types.
Here's an answer that lazily enumerates the source enumerable, but eagerly enumerates the contents of each returned list between zeroes. It properly throws upon null input or upon being given a list that does not start with a zero (though allowing an empty list through--that's really an implementation detail you have to decide on). It does not return an extra and empty list at the end like at least one other answer's possible suggestions does.
public static IEnumerable<List<int>> Parse(this IEnumerable<int> source, int splitValue = 0) {
if (source == null) {
throw new ArgumentNullException(nameof (source));
}
using (var enumerator = source.GetEnumerator()) {
if (!enumerator.MoveNext()) {
return Enumerable.Empty<List<int>>();
}
if (enumerator.Current != splitValue) {
throw new ArgumentException(nameof (source), $"Source enumerable must begin with a {splitValue}.");
}
return ParseImpl(enumerator, splitValue);
}
}
private static IEnumerable<List<int>> ParseImpl(IEnumerator<int> enumerator, int splitValue) {
var list = new List<int>();
while (enumerator.MoveNext()) {
if (enumerator.Current == splitValue) {
yield return list;
list = new List<int>();
}
else {
list.Add(enumerator.Current);
}
}
if (list.Any()) {
yield return list;
}
}
This could easily be adapted to be generic instead of int, just change Parse to Parse<T>, change int to T everywhere, and use a.Equals(b) or !a.Equals(b) instead of a == b or a != b.
You could create an extension method like this:
public static IEnumerable<IEnumerable<T>> SplitBy<T>(this IEnumerable<T> source, T value)
{
using (var e = source.GetEnumerator())
{
if (e.MoveNext())
{
var list = new List<T> { };
//In case the source doesn't start with 0
if (!e.Current.Equals(value))
{
list.Add(e.Current);
}
while (e.MoveNext())
{
if ( !e.Current.Equals(value))
{
list.Add(e.Current);
}
else
{
yield return list;
list = new List<T> { };
}
}
//In case the source doesn't end with 0
if (list.Count>0)
{
yield return list;
}
}
}
}
Then, you can do the following:
var l = new List<int> { 0, 1, 3, 5, 0, 3, 4, 0, 1, 4, 0 };
var result = l.SplitBy(0);
You could use GroupBy with a counter.
var list = new List<int> {0,1,3,5,0,3,4,0,1,4,0};
int counter = 0;
var result = list.GroupBy(x => x==0 ? counter++ : counter)
.Select(g => g.TakeWhile(x => x!=0).ToList())
.Where(l => l.Any());
Edited to fix possibility of zeroes within numbers
Here is a semi-LINQ solution:
var l = new List<int> {0,1,3,5,0,3,4,0,1,4,0};
string
.Join(",", l.Select(x => x == 0 ? "|" : x.ToString()))
.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries));
This is probably not preferable to using a loop due to performance and other reasons, but it should work.

Linq List Any can't handle Value command of generic List<List<T>>

I get this error
'T' does not contain a definition for 'Value' and no extension method 'Value' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?)
Trying to run this code
public static List<T> FindCommon<T>(List<List<T>> lists)
{
var x = from list in lists
from option in list
where lists.All(l => l.Any(o => o.Value == option.Value))
orderby option.Value
select option;
return null;
}
test code
List<List<uint>> Patterns = new List<List<uint>>();
Patterns.Add(new List<uint>() { 1, 2, 3 });
Patterns.Add(new List<uint>() { 2, 3, 4 });
Patterns.Add(new List<uint>() { 2, 3, 4 });
Patterns.Add(new List<uint>() { 1, 2, 3 });
Patterns.Add(new List<uint>() { 5, 5, 5 });
List<uint> finalOffsets = FindCommon(Patterns);
should return either
1,2,3
or
2,3,4
probably 1,2,3
Note: the return null; is because I don't know what x will return I need it to be a list.
To make your code compile, remove .Value and use the Equals method instead of ==. However, this still would not give you what you want (as far as I understand your goal).
Based on my understanding of what you are trying to do, you want to find the list that is most repeated in the master list. Here is how you can do it:
First, define a comparer that knows how to compare lists:
public class ListEqualityComparer<T> : IEqualityComparer<List<T>>
{
public bool Equals(List<T> x, List<T> y)
{
return x.SequenceEqual(y);
}
public int GetHashCode(List<T> obj)
{
//This works. But you might want to have a
//better way for calculating the hash code
return obj.Sum(x => x.GetHashCode());
}
}
And then you can use it like this:
public static List<T> FindCommon<T>(List<List<T>> lists)
{
return lists.GroupBy(x => x, new ListEqualityComparer<T>())
.OrderByDescending(g => g.Count())
.Select(g => g.Key)
.FirstOrDefault();
}
Here's how I tackled the problem myself.
public static List<T> FindCommon<T>(List<List<T>> lists)
{
List<uint> Counts = new List<uint>();
List<List<T>> Matches = new List<List<T>>();
bool Found = false;
foreach (List<T> list in lists)
{
Found = false;
for (int i = 0; i < Counts.Count; i++)
{
if (Matches[i].Count == list.Count)
{
for (int j = 0; j < list.Count; j++)
{
//they not equals
if ((dynamic)Matches[i][j] != (dynamic)list[j])
goto next_loop;
//fully equal, increase count for repeated match found.
if (j == list.Count - 1)
{
Counts[i]++;
Found = true;
break;
}
}
}
next_loop:
if (Found) break;
continue;
}
if (!Found)
{
Counts.Add(1);
Matches.Add(list);
}
}
return Matches[Counts.IndexOf(Counts.Max())];
}

Find values that appear in all lists (or arrays or collections)

Given the following:
List<List<int>> lists = new List<List<int>>();
lists.Add(new List<int>() { 1,2,3,4,5,6,7 });
lists.Add(new List<int>() { 1,2 });
lists.Add(new List<int>() { 1,2,3,4 });
lists.Add(new List<int>() { 1,2,5,6,7 });
What is the best/fastest way of identifying which numbers appear in all lists?
You can use the .net 3.5 .Intersect() extension method:-
List<int> a = new List<int>() { 1, 2, 3, 4, 5 };
List<int> b = new List<int>() { 0, 4, 8, 12 };
List<int> common = a.Intersect(b).ToList();
To do it for two lists one would use x.Intersect(y).
To do it for several we would want to do something like:
var intersection = lists.Aggregate((x, y) => x.Intersect(y));
But this won't work because the result of the lambda isn't List<int> and so it can't be fed back in. This might tempt us to try:
var intersection = lists.Aggregate((x, y) => x.Intersect(y).ToList());
But then this makes n-1 needless calls to ToList() which is relatively expensive. We can get around this with:
var intersection = lists.Aggregate(
(IEnumerable<int> x, IEnumerable<int> y) => x.Intersect(y));
Which applies the same logic, but in using explicit types in the lambda, we can feed the result of Intersect() back in without wasting time and memory creating a list each time, and so gives faster results.
If this came up a lot we can get further (slight) performance improvements by rolling our own rather than using Linq:
public static IEnumerable<T> IntersectAll<T>(this IEnumerable<IEnumerable<T>> source)
{
using(var en = source.GetEnumerator())
{
if(!en.MoveNext()) return Enumerable.Empty<T>();
var set = new HashSet<T>(en.Current);
while(en.MoveNext())
{
var newSet = new HashSet<T>();
foreach(T item in en.Current)
if(set.Remove(item))
newSet.Add(item);
set = newSet;
}
return set;
}
}
This assumes its for internal use only. If it could be called from another assembly it should have error checks, and perhaps should be defined so as to only perform the intersect operations on the first MoveNext() of the calling code:
public static IEnumerable<T> IntersectAll<T>(this IEnumerable<IEnumerable<T>> source)
{
if(source == null)
throw new ArgumentNullException("source");
return IntersectAllIterator(source);
}
public static IEnumerable<T> IntersectAllIterator<T>(IEnumerable<IEnumerable<T>> source)
{
using(var en = source.GetEnumerator())
{
if(en.MoveNext())
{
var set = new HashSet<T>(en.Current);
while(en.MoveNext())
{
var newSet = new HashSet<T>();
foreach(T item in en.Current)
if(set.Remove(item))
newSet.Add(item);
set = newSet;
}
foreach(T item in set)
yield return item;
}
}
}
(In these final two versions there's an opportunity to short-circuit if we end up emptying the set, but it only pays off if this happens relatively often, otherwise it's a nett loss).
Conversely, if these aren't concerns, and if we know that we're only ever going to want to do this with lists, we can optimise a bit further with the use of Count and indices:
public static IEnumerable<T> IntersectAll<T>(this List<List<T>> source)
{
if (source.Count == 0) return Enumerable.Empty<T>();
if (source.Count == 1) return source[0];
var set = new HashSet<T>(source[0]);
for(int i = 1; i != source.Count; ++i)
{
var newSet = new HashSet<T>();
var list = source[i];
for(int j = 0; j != list.Count; ++j)
{
T item = list[j];
if(set.Remove(item))
newSet.Add(item);
}
set = newSet;
}
return set;
}
And further if we know we're always going to want the results in a list, and we know that either we won't mutate the list, or it won't matter if the input list got mutated, we can optimise for the case of there being zero or one lists (but this costs more if we might ever not need the output in a list):
public static List<T> IntersectAll<T>(this List<List<T>> source)
{
if (source.Count == 0) return new List<T>(0);
if (source.Count == 1) return source[0];
var set = new HashSet<T>(source[0]);
for(int i = 1; i != source.Count; ++i)
{
var newSet = new HashSet<T>();
var list = source[i];
for(int j = 0; j != list.Count; ++j)
{
T item = list[j];
if(set.Remove(item))
newSet.Add(item);
}
set = newSet;
}
return new List<T>(set);
}
Again though, as well as making the method less widely-applicable, this has risks in terms of how it could be used, so is only appropriate for internal code were you can know either that you won't change either the input or the output after the fact, or that this won't matter.
Linq already offers Intersect and you can exploit Aggregate as well:
var result = lists.Aggregate((a, b) => a.Intersect(b).ToList());
If you don't trust the Intersect method or you just prefer to see what's going on, here's a snippet of code that should do the trick:
// Output goes here
List<int> output = new List<int>();
// Make sure lists are sorted
for (int i = 0; i < lists.Count; ++i) lists[i].Sort();
// Maintain array of indices so we can step through all the lists in parallel
int[] index = new int[lists.Count];
while(index[0] < lists[0].Count)
{
// Search for each value in the first list
int value = lists[0][index[0]];
// No. lists that value appears in, we want this to equal lists.Count
int count = 1;
// Search all the other lists for the value
for (int i = 1; i < lists.Count; ++i)
{
while (index[i] < lists[i].Count)
{
// Stop if we've passed the spot where value would have been
if (lists[i][index[i]] > value) break;
// Stop if we find value
if (lists[i][index[i]] == value)
{
++count;
break;
}
++index[i];
}
// If we reach the end of any list there can't be any more matches so end the search now
if (index[i] >= lists[i].Count) goto done;
}
// Store the value if we found it in all the lists
if (count == lists.Count) output.Add(value);
// Skip multiple occurrances of the same value
while (index[0] < lists[0].Count && lists[0][index[0]] == value) ++index[0];
}
done:
Edit:
I got bored and did some benchmarks on this vs. Jon Hanna's version. His is consistently faster, typically by around 50%. Mine wins by about the same margin if you happen to have presorted lists, though. Also you can gain a further 20% or so with unsafe optimisations. Just thought I'd share that.
You can also get it with SelectMany and Distinct:
List<int> result = lists
.SelectMany(x => x.Where(e => lists.All(l => l.Contains(e))))
.Distinct().ToList();
Edit:
List<int> result2 = lists.First().Where(e => lists.Skip(1).All(l => l.Contains(e)))
.ToList();
Edit 2:
List<int> result3 = lists
.Select(l => l.OrderBy(n => n).Take(lists.Min(x => x.Count()))).First()
.TakeWhile((n, index) => lists.Select(l => l.OrderBy(x => x)).Skip(1).All(l => l.ElementAt(index) == n))
.ToList();

c# Array.FindAllIndexOf which FindAll IndexOf

I know c# has Array.FindAll and Array.IndexOf.
Is there a Array.FindAllIndexOf which returns int[]?
string[] myarr = new string[] {"s", "f", "s"};
int[] v = myarr.Select((b,i) => b == "s" ? i : -1).Where(i => i != -1).ToArray();
This will return 0, 2
If the value does not exist in the array then it will return a int[0].
make an extension method of it
public static class EM
{
public static int[] FindAllIndexof<T>(this IEnumerable<T> values, T val)
{
return values.Select((b,i) => object.Equals(b, val) ? i : -1).Where(i => i != -1).ToArray();
}
}
and call it like
string[] myarr = new string[] {"s", "f", "s"};
int[] v = myarr.FindAllIndexof("s");
You can write something like :
string[] someItems = { "cat", "dog", "purple elephant", "unicorn" };
var selectedItems = someItems.Select((item, index) => new{
ItemName = item,
Position = index});
or
var Items = someItems.Select((item, index) => new{
ItemName = item,
Position = index}).Where(i => i.ItemName == "purple elephant");
Read : Get the index of a given item using LINQ
Searches for an element that matches the conditions defined by the specified predicate, and returns all the zero-based index of the occurrence within the entire System.Array.
public static int[] FindAllIndex<T>(this T[] array, Predicate<T> match)
{
return array.Select((value, index) => match(value) ? index : -1)
.Where(index => index != -1).ToArray();
}
I know this is an old post, but you can try the following,
string[] cars = {"Volvo", "BMW", "Volvo", "Mazda","BMW","BMW"};
var res = Enumerable.Range(0, cars.Length).Where(i => cars[i] == "BMW").ToList();
returns {1,4,5} as a list
No, there is not. But you can write your own extension method.
public static int[] FindAllIndexOf<T>(this T[] a, Predicate<T> match)
{
T[] subArray = Array.FindAll<T>(a, match);
return (from T item in subArray select Array.IndexOf(a, item)).ToArray();
}
and then, for your array, call it.
You can loop with findIndex giving an index
string[] arr = { "abc", "asd", "def", "abc", "lmn", "wer" };
int index = -1;
do
{
index = Array.IndexOf(arr, "abc", index + 1);
System.Console.WriteLine(index);
} while (-1 != index);
I've used Nikhil Agrawal's answer to create the following related method, which may be useful.
public static List<int> FindAllIndexOf<T>(List<T> values, List<T> matches)
{
// Initialize list
List<int> index = new List<int>();
// For each value in matches get the index and add to the list with indexes
foreach (var match in matches)
{
// Find matches
index.AddRange(values.Select((b, i) => Equals(b, match) ? i : -1).Where(i => i != -1).ToList());
}
return index;
}
Which takes a list with values and a list with values that are to be matched. It returns a list of integers with the index of the matches.
You can solve this problem by creating only 2 integer variables. More power to you!
string[] seasons= { "Fall","Spring", "Summer", "Fall", "Fall", "Winter"};
int i = 0;
int IndexOfFallInArray = 0;
int[] IndexesOfFall= new int[seasons.Length];
foreach (var item in seasons)
{
if (item == "Fall")
{
IndexesOfFall[i] = IndexOfFallInArray;
i++;
}
IndexOfFallInArray++;
}
How about simply:
public static IEnumerable<int> Available()
{
for (int i = 0; i < myarr.Length; i++)
{
if (myarr[i] is null) //Your predicate here...
yield return i;
}
}
I'm aware that the question is answered already, this is just another way of doing it. note that I used ArrayList instead of int[]
// required using directives
using System;
using System.Collections;
String inputString = "The lazy fox couldn't jump, poor fox!";
ArrayList locations = new ArrayList(); // array for found indexes
string[] lineArray = inputString.Split(' '); // inputString to array of strings separated by spaces
int tempInt = 0;
foreach (string element in lineArray)
{
if (element == "fox")
{
locations.Add(tempInt); // tempInt will be the index of current found index and added to Arraylist for further processing
}
tempInt++;
}

Categories