This question already has answers here:
How to Count Duplicates in List with LINQ
(7 answers)
Closed 9 years ago.
How can I check if there are two or more equal values in one array?
eg. in this example, i want the program to tell me that there is a pair of 2 and a pair of 4
int[] array1 = { 1, 2, 4, 2, 4 };
Using Linq
var result = array1.GroupBy(i=>i)
.Select(g=>new {Value = g.Key, Count = g.Count()})
.Where(x=>x.Count>1)
.ToList();
foreach (var pair in result)
{
Console.WriteLine("PAIR: " + pair.Value + " COUNT: " + pair.Count);
}
[EDIT] Sorry, this answers the question "How can I check if there are two or more equal values in one array?", but it doesn't tell you the actual duplicates...
This would work, but possibly it isn't the most efficient way!
int[] array1 = { 1, 2, 4, 2, 4 };
if (array1.Distinct().Count() < array1.Length)
Console.WriteLine("Contains Dupes");
If you want the most efficient approach:
bool containsDupes(int[] array)
{
for (int i = 0; i < array.Length - 1; ++i)
{
int n = array[i];
for (int j = i+1; j < array.Length; ++j)
if (array[j] == n)
return true;
}
return false;
}
I don't think you can get much more efficient than that. It will return as soon as it finds any match.
You could use a Linq Statement like:
var query =
from numbers in array1
group numbers by numbers into duplicates
where duplicates.Count() > 1
select new { Item = duplicates.Key, ItemCount = duplicates.Count() };
This will return the following:
Item 2: ItemCount 2
Item 4: ItemCount 2
Or another syntax for the same:
var query = array1.GroupBy(x => x)
.Where(x => x.Count() > 1)
.Select(x => new { x, Count = x.Count() });
You could use LINQ's GroupBy
Example:
var grouped = array1.GroupBy(x => x).Select(x => new { Value = x.Key, Count = x.Count() });
foreach(var item in grouped) {
if (item.Count == 1)
continue;
Console.WriteLine("There are {0} instances of the number {1} in the array.", item.Count, item.Value);
}
I like this syntax:
int[] array1 = { 1, 2, 4, 2, 4 };
var isThereAnyRepeated = (from i in array1
group i by i into g
where g.Count() > 1
select g).Any();
Console.WriteLine(isThereAnyRepeated);
Here's a slight variation of I4V's answer.
Instead of Select and ToList this uses ToDictionary.
using System;
using System.Linq;
namespace StackOverflow_2013_05_27_EqualValuesInArray
{
class Program
{
static void Main(string[] args)
{
int[] array = { 1, 2, 4, 2, 4 };
var tbl = array
.GroupBy(n => n)
.Where(g => g.Count() > 1)
.ToDictionary(g => g.Key, g => g.Count());
foreach (var pair in tbl)
Console.WriteLine("{0} is in array {1} times", pair.Key, pair.Value);
Console.ReadLine();
}
}
}
class item
{
int value;
int number;
}
list<item> items = new list <item>();
for(int i=0; i<array1.length;i++)
{
if (i=0)
items.add(new item(array1[i],1))
else if (array1.contains(array[i])) items.add(new item(array1[i],))
else items.add(new item(array1[i],1))
}
Related
I have some code to sort an array into ascending order
int[] array = new int[] { 4, 3, 5, 1 };
var result = array.GroupBy(x => x)
.OrderBy(g => g.Count())
.ThenBy(g => g.Key)
.SelectMany(g => g);
I would like to be able to count the number of steps required to complete the sort.
The specific question I am trying to solve is this:
You are given an unordered array consisting of consecutive integers [1, 2, 3, ..., n] without any duplicates. You are allowed to swap any two elements. You need to find the minimum number of swaps required to sort the array in ascending order.
Can I find the number of swaps used by LINQ?
Is it possible to get this?
So for example if the query had to swap 4 with 1 to get 1,3,5,4 then 5 with 4 to get 1,3,4,5 then this would be 2 steps.
This is how I came up. I couldn't find the way using it with LINQ however with our own Sorting Algorithm. I did something like this:
static void Main(string[] args)
{
ObservableCollection<int> array = new ObservableCollection<int>() {4,3,1,5 };
int steps = 0;
array.CollectionChanged+= (sender, e) =>
{
Console.WriteLine($"{e.Action} : {string.Join(",", array) }" );
steps++;
};
bool didSwap;
do
{
didSwap = false;
for (int i = 0; i < array.Count - 1; i++)
{
if (array[i] > array[i + 1])
{
int temp = array[i + 1];
array[i + 1] = array[i];
array[i] = temp;
didSwap = true;
}
}
} while (didSwap);
Console.WriteLine("Sorted Result :");
foreach(var item in array)
{
Console.WriteLine(item);
}
Console.WriteLine($"Total Swapps {steps / 2}");
Console.ReadLine();
}
This is the output:
How do I select the unique elements from the list {0, 1, 2, 2, 2, 3, 4, 4, 5} so that I get {0, 1, 3, 5}, effectively removing all instances of the repeated elements {2, 4}?
var numbers = new[] { 0, 1, 2, 2, 2, 3, 4, 4, 5 };
var uniqueNumbers =
from n in numbers
group n by n into nGroup
where nGroup.Count() == 1
select nGroup.Key;
// { 0, 1, 3, 5 }
var nums = new int{ 0...4,4,5};
var distinct = nums.Distinct();
make sure you're using Linq and .NET framework 3.5.
With lambda..
var all = new[] {0,1,1,2,3,4,4,4,5,6,7,8,8}.ToList();
var unique = all.GroupBy(i => i).Where(i => i.Count() == 1).Select(i=>i.Key);
C# 2.0 solution:
static IEnumerable<T> GetUniques<T>(IEnumerable<T> things)
{
Dictionary<T, int> counts = new Dictionary<T, int>();
foreach (T item in things)
{
int count;
if (counts.TryGetValue(item, out count))
counts[item] = ++count;
else
counts.Add(item, 1);
}
foreach (KeyValuePair<T, int> kvp in counts)
{
if (kvp.Value == 1)
yield return kvp.Key;
}
}
Here is another way that works if you have complex type objects in your List and want to get the unique values of a property:
var uniqueValues= myItems.Select(k => k.MyProperty)
.GroupBy(g => g)
.Where(c => c.Count() == 1)
.Select(k => k.Key)
.ToList();
Or to get distinct values:
var distinctValues = myItems.Select(p => p.MyProperty)
.Distinct()
.ToList();
If your property is also a complex type you can create a custom comparer for the Distinct(), such as Distinct(OrderComparer), where OrderComparer could look like:
public class OrderComparer : IEqualityComparer<Order>
{
public bool Equals(Order o1, Order o2)
{
return o1.OrderID == o2.OrderID;
}
public int GetHashCode(Order obj)
{
return obj.OrderID.GetHashCode();
}
}
If Linq isn't available to you because you have to support legacy code that can't be upgraded, then declare a Dictionary, where the first int is the number and the second int is the number of occurences. Loop through your List, loading up your Dictionary. When you're done, loop through your Dictionary selecting only those elements where the number of occurences is 1.
I believe Matt meant to say:
static IEnumerable<T> GetUniques<T>(IEnumerable<T> things)
{
Dictionary<T, bool> uniques = new Dictionary<T, bool>();
foreach (T item in things)
{
if (!(uniques.ContainsKey(item)))
{
uniques.Add(item, true);
}
}
return uniques.Keys;
}
There are many ways to skin a cat, but HashSet seems made for the task here.
var numbers = new[] { 0, 1, 2, 2, 2, 3, 4, 4, 5 };
HashSet<int> r = new HashSet<int>(numbers);
foreach( int i in r ) {
Console.Write( "{0} ", i );
}
The output:
0 1 2 3 4 5
Here's a solution with no LINQ:
var numbers = new[] { 0, 1, 2, 2, 2, 3, 4, 4, 5 };
// This assumes the numbers are sorted
var noRepeats = new List<int>();
int temp = numbers[0]; // Or .First() if using IEnumerable
var count = 1;
for(int i = 1; i < numbers.Length; i++) // Or foreach (var n in numbers.Skip(1)) if using IEnumerable
{
if (numbers[i] == temp) count++;
else
{
if(count == 1) noRepeats.Add(temp);
temp = numbers[i];
count = 1;
}
}
if(count == 1) noRepeats.Add(temp);
Console.WriteLine($"[{string.Join(separator: ",", values: numbers)}] -> [{string.Join(separator: ",", values: noRepeats)}]");
This prints:
[0,1,2,2,2,3,4,4,5] -> [0,1,3,5]
In .Net 2.0 I`m pretty sure about this solution:
public IEnumerable<T> Distinct<T>(IEnumerable<T> source)
{
List<T> uniques = new List<T>();
foreach (T item in source)
{
if (!uniques.Contains(item)) uniques.Add(item);
}
return uniques;
}
This question already has answers here:
c# Array.FindAllIndexOf which FindAll IndexOf
(10 answers)
Closed 8 years ago.
How to find all positions of a value in array
class Program
{
static void Main(string[] args)
{
int start = 0;
int[] numbers = new int[7] { 2,1,2,1,5,6,5};
}
Something like that:
int[] numbers = new [] { 2, 1, 2, 1, 5, 6, 5 };
int toFind = 5;
// all indexes of "5" {4, 6}
int[] indexes = numbers
.Select((v, i) => new {
value = v,
index = i
})
.Where(pair => pair.value == toFind)
.Select(pair => pair.index)
.ToArray();
List<int> indexes = new List<int>();
for (int i = 0; i < numbers.Length; i++)
{
if (numbers[i] == yourNumber)
indexes.Add(i);
}
Useage is: Array.indexOf(T,value)
please refere to the msdn below.
http://msdn.microsoft.com/en-us/library/system.array.indexof(v=vs.110).aspx
You can make a really simple extension method for sequences to do this:
public static class SequenceExt
{
public static IEnumerable<int> IndicesOfAllElementsEqualTo<T>
(
this IEnumerable<T> sequence,
T target
) where T: IEquatable<T>
{
int index = 0;
foreach (var item in sequence)
{
if (item.Equals(target))
yield return index;
++index;
}
}
}
The extension method works with List<>, arrays, IEnumerable<T> and other collections.
Then your code would look something like this:
var numbers = new [] { 2, 1, 2, 1, 5, 6, 5 };
var indices = numbers.IndicesOfAllElementsEqualTo(5); // Use extension method.
// Make indices into an array if you want, like so
// (not really necessary for this sample code):
var indexArray = indices.ToArray();
// This prints "4, 6":
Console.WriteLine(string.Join(", ", indexArray));
Linq could help
var indexes = numbers
.Select((x, idx) => new { x, idx })
.Where(c => c.x == number)
.Select(c => c.idx);
Here is an scenario of my question: I have an array, say:
{ 4, 1, 1, 3, 3, 2, 5, 3, 2, 2 }
The result should be something like this (array element => its count):
4 => 1
1 => 2
3 => 2
2 => 1
5 => 1
3 => 1
2 => 2
I know this can be achieved by for loop.
But google'd a lot to make this possible using lesser lines of code using LINQ without success.
I believe the most optimal way to do this is to create a "LINQ-like" extension methods using an iterator block. This allows you to perform the calculation doing a single pass over your data. Note that performance isn't important at all if you just want to perform the calculation on a small array of numbers. Of course this is really your for loop in disguise.
static class Extensions {
public static IEnumerable<Tuple<T, Int32>> ToRunLengths<T>(this IEnumerable<T> source) {
using (var enumerator = source.GetEnumerator()) {
// Empty input leads to empty output.
if (!enumerator.MoveNext())
yield break;
// Retrieve first item of the sequence.
var currentValue = enumerator.Current;
var runLength = 1;
// Iterate the remaining items in the sequence.
while (enumerator.MoveNext()) {
var value = enumerator.Current;
if (!Equals(value, currentValue)) {
// A new run is starting. Return the previous run.
yield return Tuple.Create(currentValue, runLength);
currentValue = value;
runLength = 0;
}
runLength += 1;
}
// Return the last run.
yield return Tuple.Create(currentValue, runLength);
}
}
}
Note that the extension method is generic and you can use it on any type. Values are compared for equality using Object.Equals. However, if you want to you could pass an IEqualityComparer<T> to allow for customization of how values are compared.
You can use the method like this:
var numbers = new[] { 4, 1, 1, 3, 3, 2, 5, 3, 2, 2 };
var runLengths = numbers.ToRunLengths();
For you input data the result will be these tuples:
4 1
1 2
3 2
2 1
5 1
3 1
2 2
(Adding another answer to avoid the two upvotes for my deleted one counting towards this...)
I've had a little think about this (now I've understood the question) and it's really not clear how you'd do this nicely in LINQ. There are definitely ways that it could be done, potentially using Zip or Aggregate, but they'd be relatively unclear. Using foreach is pretty simple:
// Simplest way of building an empty list of an anonymous type...
var results = new[] { new { Value = 0, Count = 0 } }.Take(0).ToList();
// TODO: Handle empty arrays
int currentValue = array[0];
int currentCount = 1;
foreach (var value in array.Skip(1))
{
if (currentValue != value)
{
results.Add(new { Value = currentValue, Count = currentCount });
currentCount = 0;
currentValue = value;
}
currentCount++;
}
// Handle tail, which we won't have emitted yet
results.Add(new { Value = currentValue, Count = currentCount });
Here's a LINQ expression that works (edit: tightened up code just a little more):
var data = new int[] { 4, 1, 1, 3, 3, 2, 5, 3, 2, 2 };
var result = data.Select ((item, index) =>
new
{
Key = item,
Count = (index == 0 || data.ElementAt(index - 1) != item)
? data.Skip(index).TakeWhile (d => d == item).Count ()
: -1
}
)
.Where (d => d.Count != -1);
And here's a proof that shows it working.
This not short enough?
public static IEnumerable<KeyValuePair<T, int>> Repeats<T>(
this IEnumerable<T> source)
{
int count = 0;
T lastItem = source.First();
foreach (var item in source)
{
if (Equals(item, lastItem))
{
count++;
}
else
{
yield return new KeyValuePair<T, int>(lastItem, count);
lastItem = item;
count = 1;
}
}
yield return new KeyValuePair<T, int>(lastItem, count);
}
I'll be interested to see a linq way.
I already wrote the method you need over there. Here's how to call it.
foreach(var g in numbers.GroupContiguous(i => i))
{
Console.WriteLine("{0} => {1}", g.Key, g.Count);
}
Behold (you can run this directly in LINQPad -- rle is where the magic happens):
var xs = new[] { 4, 1, 1, 3, 3, 2, 5, 3, 2, 2 };
var rle = Enumerable.Range(0, xs.Length)
.Where(i => i == 0 || xs[i - 1] != xs[i])
.Select(i => new { Key = xs[i], Count = xs.Skip(i).TakeWhile(x => x == xs[i]).Count() });
Console.WriteLine(rle);
Of course, this is O(n^2), but you didn't request linear efficiency in the spec.
var array = new int[] {1,1,2,3,5,6,6 };
foreach (var g in array.GroupBy(i => i))
{
Console.WriteLine("{0} => {1}", g.Key, g.Count());
}
var array = new int[]{};//whatever ur array is
array.select((s)=>{return array.where((s2)=>{s == s2}).count();});
the only prob with is tht if you have 1 - two times you will get the result for 1-two times
var array = new int[] {1,1,2,3,5,6,6 };
var arrayd = array.Distinct();
var arrayl= arrayd.Select(s => { return array.Where(s2 => s2 == s).Count(); }).ToArray();
Output
arrayl=[0]2 [1]1 [2]1 [3]1 [4]2
Try GroupBy through List<int>
List<int> list = new List<int>() { 4, 1, 1, 3, 3, 2, 5, 3, 2, 2 };
var res = list.GroupBy(val => val);
foreach (var v in res)
{
MessageBox.Show(v.Key.ToString() + "=>" + v.Count().ToString());
}
var nums = new[]{ 1, 2, 3, 4, 5, 6, 7};
var pairs = /* some linq magic here*/ ;
=>
pairs = { {1, 2}, {3, 4}, {5, 6}, {7, 0} }
The elements of pairs should be either two-element lists, or instances of some anonymous class with two fields, something like new {First = 1, Second = 2}.
None of the default linq methods can do this lazily and with a single scan. Zipping the sequence with itself does 2 scans and grouping is not entirely lazy. Your best bet is to implement it directly:
public static IEnumerable<T[]> Partition<T>(this IEnumerable<T> sequence, int partitionSize) {
Contract.Requires(sequence != null)
Contract.Requires(partitionSize > 0)
var buffer = new T[partitionSize];
var n = 0;
foreach (var item in sequence) {
buffer[n] = item;
n += 1;
if (n == partitionSize) {
yield return buffer;
buffer = new T[partitionSize];
n = 0;
}
}
//partial leftovers
if (n > 0) yield return buffer;
}
Try this:
int i = 0;
var pairs =
nums
.Select(n=>{Index = i++, Number=n})
.GroupBy(n=>n.Index/2)
.Select(g=>{First:g.First().Number, Second:g.Last().Number});
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7 };
var result = numbers.Zip(numbers.Skip(1).Concat(new int[] { 0 }), (x, y) => new
{
First = x,
Second = y
}).Where((item, index) => index % 2 == 0);
(warning: looks ugly)
var pairs = x.Where((i, val) => i % 2 == 1)
.Zip(
x.Where((i, val) => i % 2 == 0),
(first, second) =>
new
{
First = first,
Second = second
})
.Concat(x.Count() % 2 == 1 ? new[]{
new
{
First = x.Last(),
Second = default(int)
}} : null);
This might be a bit more general than you require - you can set a custom itemsInGroup:
int itemsInGroup = 2;
var pairs = nums.
Select((n, i) => new { GroupNumber = i / itemsInGroup, Number = n }).
GroupBy(n => n.GroupNumber).
Select(g => g.Select(n => n.Number).ToList()).
ToList();
EDIT:
If you want to append zeros (or some other number) in case the last group is of a different size:
int itemsInGroup = 2;
int valueToAppend = 0;
int numberOfItemsToAppend = itemsInGroup - nums.Count() % itemsInGroup;
var pairs = nums.
Concat(Enumerable.Repeat(valueToAppend, numExtraItems)).
Select((n, i) => new { GroupNumber = i / itemsInGroup, Number = n }).
GroupBy(n => n.GroupNumber).
Select(g => g.Select(n => n.Number).ToList()).
ToList();
public static IEnumerable<List<T>> InSetsOf<T>(this IEnumerable<T> source, int max)
{
return InSetsOf(source, max, false, default(T));
}
public static IEnumerable<List<T>> InSetsOf<T>(this IEnumerable<T> source, int max, bool fill, T fillValue)
{
var toReturn = new List<T>(max);
foreach (var item in source)
{
toReturn.Add(item);
if (toReturn.Count == max)
{
yield return toReturn;
toReturn = new List<T>(max);
}
}
if (toReturn.Any())
{
if (fill)
{
toReturn.AddRange(Enumerable.Repeat(fillValue, max-toReturn.Count));
}
yield return toReturn;
}
}
usage:
var pairs = nums.InSetsOf(2, true, 0).ToArray();
IList<int> numbers = new List<int> {1, 2, 3, 4, 5, 6, 7};
var grouped = numbers.GroupBy(num =>
{
if (numbers.IndexOf(num) % 2 == 0)
{
return numbers.IndexOf(num) + 1;
}
return numbers.IndexOf(num);
});
If you need the last pair filled with zero you could just add it before doing the grouping if the listcount is odd.
if (numbers.Count() % 2 == 1)
{
numbers.Add(0);
}
Another approach could be:
var groupedIt = numbers
.Zip(numbers.Skip(1).Concat(new[]{0}), Tuple.Create)
.Where((x,i) => i % 2 == 0);
Or you use MoreLinq that has a lot of useful extensions:
IList<int> numbers = new List<int> {1, 2, 3, 4, 5, 6, 7};
var batched = numbers.Batch(2);
var w =
from ei in nums.Select((e, i) => new { e, i })
group ei.e by ei.i / 2 into g
select new { f = g.First(), s = g.Skip(1).FirstOrDefault() };
var nums = new float[] { 1, 2, 3, 4, 5, 6, 7 };
var enumerable =
Enumerable
.Range(0, nums.Length)
.Where(i => i % 2 == 0)
.Select(i =>
new { F = nums[i], S = i == nums.Length - 1 ? 0 : nums[i + 1] });
Another option is to use the SelectMany LINQ method. This is more for those who wish to iterate through a list of items and for each item return 2 or more of it's properties. No need to loop through the list again for each property, just once.
var list = new [] {//Some list of objects with multiple properties};
//Select as many properties from each Item as required.
IEnumerable<string> flatList = list.SelectMany(i=> new[]{i.NameA,i.NameB,i.NameC});
Another simple solution using index and index + 1.
var nums = Enumerable.Range(1, 10);
var pairs = nums.Select((item, index) =>
new { First = item, Second = nums.ElementAtOrDefault(index + 1) })
.SkipLastN(1);
pairs.ToList().ForEach(p => Console.WriteLine($"({p.First}, {p.Second}) "));
Last item is invalid and must be removed with SkipLastN().
this gives all possible pairs(vb.net):
Dim nums() = {1, 2, 3, 4, 5, 6, 7}
Dim pairs = From a In nums, b In nums Where a <> b Select a, b
Edit:
Dim allpairs = From a In nums, b In nums Where b - a = 1 Select a, b
Dim uniquePairs = From p In allpairs Where p.a Mod 2 <> 0 Select p
note: the last pair is missing, working on it
Edit:
union uniquePairs with the pair {nums.Last,0}