I have this code:
public List<int> Duplicates(List<int> sequence)
{
int[] countArr = new int[156];
foreach (int i in sequence)
{
countArr[i]++;
}
List<int> resultList = new List<int>();
for (var i = 0; i < countArr.Length; i++)
{
if (countArr[i] > 1)
{
resultList.Add(i);
}
}
return resultList;
}
This is getting me the elements that are duplicated, but not how many times this elements are duplicated.
Thanks in advance for any help provided.
EDIT
I do not want to use LINQ
Use GroupBy:
sequence.GroupBy(i => i).Select(g => new {Value = g.Key, Amount = g.Count()})
If you don't want to use Linq (why???) just collect value and amount together in a Tuple:
List<Tuple<int,int>> resultList = new List<Tuple<int,int>>();
for (var i = 0; i < countArr.Length; i++)
{
if (countArr[i] > 1)
{
resultList.Add(Tuple.Create(i, countArr[i]));
}
}
That's a very complicated way you use, i'd rather return a Dictionary<int, int>:
public static Dictionary<int, int> Duplicates(IEnumerable<int> sequence)
{
var duplicates = new Dictionary<int, int>();
foreach (int i in sequence)
{
if(duplicates.ContainsKey(i))
duplicates[i]++;
else
duplicates.Add(i, 1);
}
return duplicates;
}
Your algorithm already produces the required counts, so all you need to do is to arrange returning them to the caller in some way. One approach is to change the return type to IList<KeyValuePair<int,int>>. The collection of pairs you return would contain the number in the Key property, and its count in the Value property:
IList<KeyValuePair<int,int>> Duplicates(List<int> sequence) {
var countArr = new int[156];
foreach (int i in sequence) {
countArr[i]++;
}
var resultList = new List<KeyValuePair<int,int>>();
for (var i = 0; i < countArr.Length; i++) {
if (countArr[i] > 1) {
resultList.Add(new KeyValuePair<int,int>(i, countArr[i]));
}
}
return resultList;
}
Simple answer with dictionary:
void Main()
{
List<int> intlist = new List<int>
{
1,
1,
1,
2,
2,
3,
4,
4,
4,
4
};
var dict = new Dictionary<int, int>();
foreach (var item in intlist)
{
if (!dict.ContainsKey(item)) // this checks for the existance of an item
{
dict.Add(item, 0); // this initialises the item in the dictionary
}
dict[item]++; // this will update the count of the item
}
// this is just for linqpad debug output and shows each value and their count
// this can be achieved with foreach
dict.Select(x => new { x.Key, x.Value}).Dump();
}
Yes I know there is a Select at the bottom, but that has nothing to do with the duplicate collection.
Related
I am trying to converting from dictionary to list while converting I am getting the output
I/p-
dic.Add("Demo1",2);
dic.Add("Demo2",1);
dic.Add("Demo3",1);
dic.Add("Demo4",2);
O/p-
Demo1
Demo2
Demo3
Demo4
But I need Demo1 and Demo4 two times because their quantity are 2. So How can I achieve that??
Below is the code
public IList<string> DictionaryToList(IDictionary<string,int> dictionary)
{
IDictionary<string, int> dic = new Dictionary<string, int>();
IList<string> lst = new List<string>();
dic.Add("Demo1",2);
dic.Add("Demo2",1);
dic.Add("Demo3",1);
dic.Add("Demo4",2);
foreach (var item in dic)
{
if (!lst.Contains(item.Key))
{
lst.Add(item.Key);
}
}
return lst;
}
}
class Program
{
static void Main(string[] args)
{
var conversion = new Conversion();
var list = new List<string> { "Demo1","Demo2","Demo3","Demo4","Demo1","Demo4"};
var dictionary = conversion.ListToDictionary(list);
foreach (var item in dictionary)
{
Console.WriteLine($"{item.Key}, {item.Value}");
}
var convertedList = conversion.DictionaryToList(dictionary);
foreach (var item in convertedList)
{
Console.WriteLine($"{item}");
}
Console.ReadLine();
}
Thanks in advance.
You can use LINQ's SelectMany and Enumerable.Repeat:
IList<string> list = dictionary
.SelectMany(kv => Enumerable.Repeat(kv.Key, kv.Value))
.ToList();
Here is also the opposite way to build your dictionary from the list:
var list = new List<string> { "Demo1", "Demo2", "Demo3", "Demo4", "Demo1", "Demo4" };
var dictionary = list.GroupBy(s => s).ToDictionary(g => g.Key, g => g.Count());
IList<string> list2 = dictionary
.SelectMany(kv => Enumerable.Repeat(kv.Key, kv.Value))
.ToList();
So at the end list2 contains the same strings as list but in a different order.
Your dictionary consists of a key (string) and a value (int). After checking
if (!list.Contains(item.Key)) just add another loop which goes from 0 to the actual value from your dictionary-item and adds the new item n-times.
for (int i = 0; i < item.Value; i++) // Demo1 and Demo4 runs 2x, Demo2 and Demo3 1x
lst.Add(item.Key);
Do you want something like this?
Dictionary<string, int> dic = new Dictionary<string, int>();
List<string> lst = new List<string>();
dic.Add("Demo1", 2);
dic.Add("Demo2", 1);
dic.Add("Demo3", 1);
dic.Add("Demo4", 2);
foreach (var item in dic)
{
for (int i = 0; i < item.Value; i++)
{
lst.Add(item.Key);
}
}
I have List<List<int>>, For example
List<List<int>> has {{1,2,3}, {1,1,2,}, {1,2,3}}.
I want to remove duplicate in this:
Result should be: {{1,2,3}, {1,1,2}}
The problem is the inner lists are reference types so they have different object hashcode and hence are treated separate.
I don't want to iterate list completely to find duplicates as its not optimum.
Try this:
List<List<int>> lst = new List<List<int>>()
{
new List<int> {1,2,3},
new List<int> {1,1,2},
new List<int> {1,2,3}
};
var result = lst.GroupBy(c => String.Join(",", c)).Select(c => c.First().ToList()).ToList();
You can implement an EqualityComparer class and use it in Distinct method of LINQ.
public class CustomEqualityComparer : IEqualityComparer<List<int>>
{
public bool Equals(List<int> x, List<int> y)
{
if (x.Count != y.Count)
return false;
for (int i = 0; i < x.Count; i++)
{
if (x[i] != y[i])
return false;
}
return true;
}
public int GetHashCode(List<int> obj)
{
return 0;
}
}
and use it like this
public static void Main(string[] args)
{
var list = new List<List<int>>() { new List<int> { 1, 1, 2 }, new List<int> { 1, 2, 3 }, new List<int> { 1, 1, 2 } };
var res = list.Distinct(new CustomEqualityComparer());
Console.WriteLine("Press any key to continue.");
Console.ReadLine();
}
It's very simple:
List<List<int>> lst = new List<List<int>>()
{
new List<int> {1,2,3},
new List<int> {1,1,2,},
new List<int> {1,2,3},
};
var result =
lst
.Where((xs, n) =>
!lst
.Skip(n + 1)
.Any(ys => xs.SequenceEqual(ys)))
.ToList();
I get this result:
What you want is more complicated than simple comparision.
In my point of view you should create a new type / class like
IntegerCollection : ICollection
Then you should implement Equals in that way:
bool Equals(IntegerCollection col) { if(this.Count() != col.Count())
return false;
if(this.Sum() != col.Sum())
return false;
for(int i = 0; i < this.Count(); i++) {
if(this[i]==col[i]){
continue;
}else{
return false;
} }
return true; }
And finally
List<IntegerCollection> collections = new List<IntegerCollection> {
new IntegerCollection({1,2,3}),
new IntegerCollection({1,1,2}),
new IntegerCollection({1,2,3})};
var distincts = collections.Distinct();
Using #farid's CustomEqualityComparer you can also make use of HashSet:
List<List<int>> RemoveDuplicates(IEnumerable<List<int>> values)
{
return new HashSet<List<int>>(values,new CustomEqualityComparer()).ToList();
}
I've got a dictionary that for each key lists its dependencies:
parent[2] = 1 (2 depends on 1)
parent[3] = 1 (3 depends on 1)
parent[4] = {2,3} (4 depends on 2, or 4 depends on 3)
I want to build lists out of this dictionary:
[4,2,1]
[4,3,1]
I've got the suspicion I should use a recursive algorithm. Any hints?
EDIT: this is what I have so far:
How I call the recursive function:
var result = new List<List<Node<TData, TId>>>();
GetResult(parent, target, result);
return result;
And the recursive function itself:
private static List<Node<TData, TId>> GetResult<TData, TId>(Dictionary<Node<TData, TId>, List<Node<TData, TId>>> parent, Node<TData, TId> index,
List<List<Node<TData, TId>>> finalList)
where TData : IIdentifiable<TId>
where TId : IComparable
{
var newResult = new List<Node<TData, TId>> { index };
if (parent.ContainsKey(index))
{
if (parent[index].Count == 1)
{
return new List<Node<TData, TId>> { index, parent[index].First()};
}
foreach (var child in parent[index])
{
var temp = newResult.Union(GetResult(parent, child, finalList)).ToList();
finalList.Add(temp);
}
}
return newResult;
}
You could try to adapt for your needs the following code:
public static List<List<int>> FindParents(Dictionary<int, List<int>> parents, int index)
{
List<int> prefix = new List<int>();
List<List<int>> results = new List<List<int>>();
FindParentsInternal(parents, index, prefix, results);
return results;
}
private static void FindParentsInternal(Dictionary<int, List<int>> parents, int index,
List<int> prefix, List<List<int>> results)
{
var newPrefix = new List<int>(prefix) { index };
if (!parents.ContainsKey(index))
{
results.Add(newPrefix);
return;
}
parents[index].ForEach(i => FindParentsInternal(parents, i, newPrefix, results));
}
Usage:
Dictionary<int, List<int>> parents = new Dictionary<int, List<int>>
{
{ 2, new List<int> { 1 } },
{ 3, new List<int> { 1 } },
{ 4, new List<int> { 2, 3 } }
};
var t = FindParents(parents, 4);
You can benefit by keeping a dictionary of results - that way you won't need to keep recomputing them.
Dictionary<Int, Set<Int>> results;
Set<Int> getResult(int index) {
Set<Int> dictResult = results.get(index);
if(dictResult != null) {
// result has already been computed
return dictResult;
} else {
// compute result, store in dictResult
Set<Int> newResult = // compute dependency set
dictResult.put(index, newResult);
return newResult;
}
}
As for the // compute dependency list part, you can do something like the following:
Set<Int> newResult = new Set(index);
if(dict.containsKey(index)) {
List<Int> dependencies = dict.get(index);
foreach(int subIndex in dependencies) {
newResult = newResult.union(getResult(subIndex));
}
}
Your base case is when the index is not in dict (i.e. dict.containsKey returns false), e.g. 1 for the data you provided.
Here i used linq to filter my result in an array and pass into a list and from that list into a dictionary as you can see below
//array is a multidimensional array with string data in it
var datumn = array;
var list = new List<string>();
var stringcounts = new Dictionary<int,List<string>>();
var listtemp = new List<string>();
//linq
var arrayresult = from string a in datumn where a != "FREE" select a;
//adding result from arrayresult to list
foreach (var listing in arrayresult)
{
list.Add(listing);
}
//using linq again i filter my list then add to dictionary
for (int count = 3; count > 0; count-- )
{
var duplicateItems = from x in list
group x by x into grouped
where grouped.Count() == count
select grouped.Key;
foreach (var replace in duplicateItems)
{
listtemp.Add(replace.ToString());
}
stringcounts.Add(count, lists);
//clearing the list to avoid duplicating data in my dictionary
listtemp.Clear();
}
for (int key = stringcounts.Count; key > 0; --key)
{
var holding = stringcounts[key];
foreach (var li in holding)
{
MessageBox.Show(li.ToString());
//just view what i have to check if the data is correct
}
}
`
the program skips iterator over of the lists and ends can some one help with this
and i have tried everything including linq and other collections like hashtable
and maps but nothing works and it is not a console application
This line is wrong:
var dict = new Dictionary<int, List<string>>();
Remove the ";".
Result:
indigo silver violet purple green pink red brown yellow
Edit: full code for comparison:
var dict = new Dictionary<int, List<string>>()
{
{1, new List<string>{"red", "brown", "yellow"}},
{2, new List<string>{"purple", "green", "pink"}},
{3, new List<string>{"indigo", "silver", "violet"}}
};
// now i want to get my values from the lists in the dictionary
for (int count = 3; count > 0; count--)
{
var l = dict[count];
foreach (var li in l)
{
li.Dump();
}
}
foreach (var item in dict)
{
var list = item.Value;
foreach (var str in list)
{
MessageBox.Show(str);
}
}
The listtemp.Clear() is a bad syntax so therefore it should be removed and the listtemp should be declared in the for loop therefore removing redundancy and the initial problem
How to convert a String[] to an IDictionary<String, String>?
The values at the indices 0,2,4,... shall be keys, and consequently values at the indices 1,3,5,... shall be values.
Example:
new[] { "^BI", "connectORCL", "^CR", "connectCR" }
=>
new Dictionary<String, String> {{"^BI", "connectORCL"}, {"^CR", "connectCR"}};
I'd recommend a good old for loop for clarity. But if you insist on a LINQ query, this should work:
var dictionary = Enumerable.Range(0, array.Length/2)
.ToDictionary(i => array[2*i], i => array[2*i+1])
Dictionary<string,string> ArrayToDict(string[] arr)
{
if(arr.Length%2!=0)
throw new ArgumentException("Array doesn't contain an even number of entries");
Dictionary<string,string> dict=new Dictionary<string,string>();
for(int i=0;i<arr.Length/2;i++)
{
string key=arr[2*i];
string value=arr[2*i+1];
dict.Add(key,value);
}
return dict;
}
There's really no easy way to do this in LINQ (And even if there were, it's certainly not going to be clear as to the intent). It's easily accomplished by a simple loop though:
// This code assumes you can guarantee your array to always have an even number
// of elements.
var array = new[] { "^BI", "connectORCL", "^CR", "connectCR" };
var dict = new Dictionary<string, string>();
for(int i=0; i < array.Length; i+=2)
{
dict.Add(array[i], array[i+1]);
}
Something like this maybe:
string[] keyValues = new string[20];
Dictionary<string, string> dict = new Dictionary<string, string>();
for (int i = 0; i < keyValues.Length; i+=2)
{
dict.Add(keyValues[i], keyValues[i + 1]);
}
Edit: People in the C# tag are damn fast...
If you have Rx as a dependency you can do:
strings
.BufferWithCount(2)
.ToDictionary(
buffer => buffer.First(), // key selector
buffer => buffer.Last()); // value selector
BufferWithCount(int count) takes the first count values from the input sequence and yield them as a list, then it takes the next count values and so on. I.e. from your input sequence you will get the pairs as lists: {"^BI", "connectORCL"}, {"^CR", "connectCR"}, the ToDictionary then takes the first list item as key and the last ( == second for lists of two items) as value.
However, if you don't use Rx, you can use this implementation of BufferWithCount:
static class EnumerableX
{
public static IEnumerable<IList<T>> BufferWithCount<T>(this IEnumerable<T> source, int count)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (count <= 0)
{
throw new ArgumentOutOfRangeException("count");
}
var buffer = new List<T>();
foreach (var t in source)
{
buffer.Add(t);
if (buffer.Count == count)
{
yield return buffer;
buffer = new List<T>();
}
}
if (buffer.Count > 0)
{
yield return buffer;
}
}
}
It looks like other people have already beaten me to it and/or have more efficient answers but I'm posting 2 ways:
A for loop might be the clearest way to accomplish in this case...
var words = new[] { "^BI", "connectORCL", "^CR", "connectCR" };
var final = words.Where((w, i) => i % 2 == 0)
.Select((w, i) => new[] { w, words[(i * 2) + 1] })
.ToDictionary(arr => arr[0], arr => arr[1])
;
final.Dump();
//alternate way using zip
var As = words.Where((w, i) => i % 2 == 0);
var Bs = words.Where((w, i) => i % 2 == 1);
var dictionary = new Dictionary<string, string>(As.Count());
var pairs = As.Zip(Bs, (first, second) => new[] {first, second})
.ToDictionary(arr => arr[0], arr => arr[1])
;
pairs.Dump();
FYI, this is what I ended up with using a loop and implementing it as an extension method:
internal static Boolean IsEven(this Int32 #this)
{
return #this % 2 == 0;
}
internal static IDictionary<String, String> ToDictionary(this String[] #this)
{
if (!#this.Length.IsEven())
throw new ArgumentException( "Array doesn't contain an even number of entries" );
var dictionary = new Dictionary<String, String>();
for (var i = 0; i < #this.Length; i += 2)
{
var key = #this[i];
var value = #this[i + 1];
dictionary.Add(key, value);
}
return dictionary;
}
Pure Linq
Select : Project original string value and its index.
GroupBy : Group adjacent pairs.
Convert each group into dictionary entry.
string[] arr = new string[] { "^BI", "connectORCL", "^CR", "connectCR" };
var dictionary = arr.Select((value,i) => new {Value = value,Index = i})
.GroupBy(value => value.Index / 2)
.ToDictionary(g => g.FirstOrDefault().Value,
g => g.Skip(1).FirstOrDefault().Value);