Selecting array values from specific indexes order by index array - c#

I want to select array values from specific indexes
Now I have this.
var xs = new[] { 11,12,13,14,15 };
var ind = new[] { 3,2,1,0 };
var results = xs.Where((x, idx) => ind.Contains(idx)).ToArray();
The result is {11,12,13,14}
However, I want my result to be ordered by index array which should be {14,13,12,11}
Thank you very much

var results = ind.Select(i => xs[i]).ToArray();

var array = xs.Zip(ind, (x, i) => new Tuple<int, int>(x, i))
.OrderBy(t => t.Item2)
.Select(t => t.Item1)
.ToArray();

Related

C# Linq Find all indexes of item in List<int> within another List<int>

I have a List looks like:
List<int> List1= new List<int>(){3,4,5};
and another looks like:
List<int> List2 = new List<int>(){1,2,3,4,5,6};
How can I use Linq to get an array of all of the indices of List1 from List2 like below:
var ResultList = {2,3,4};
var ResultList = List1.Select(x => List2.IndexOf(x));
This is a longer solution but prevents a nested loop through the array which may be faster if the arrays are huge (but slower if the arrays are small).
List<int> List1= new List<int>(){3,4,5};
List<int> List2 = new List<int>(){1,2,3,4,5,6};
var lookup = new Dictionary<int, int>();
for(var i=0; i<List2.Count; i++) {
lookup[List2[i]] = i;
}
List<int> Result = List1.Select(i => {
int index;
return lookup.TryGetValue(i, out index) ? index : -1;
}).ToList();
You can also do the overloaded version of Select statement to select the Value and return the Index:
var result = List2.Select((a, b) => new {Value = a, Index = b})
.Where(x => List1.Any(d => d == x.Value))
.Select(c => c.Index).ToArray();
If your List2 contains more than one instance of a List1 value (or Equality) type, then you can use the indexed overload of Select to find all the duplicates:
var List1= new List<int>(){3,4,5};
var List2 = new List<int>(){1,2,3,4,5,6,1,2,3,5};
var result = List2.Select((x, idx) => Tuple.Create(x, idx))
.Where(t => List1.Contains(t.Item1))
.Select(x => x.Item2)
// 2,3,4,8,9
or better, using C#7 Value Tuples
List2.Select((x, idx) => (X:x, Idx:idx))
.Where(t => List1.Contains(t.X))
.Select(x => x.Idx);
(.IndexOf returns just the first index found in the target)

How to find duplicate values in List<Dictionary<string, object>>?

I have a List of Dictionary<string, object>.
How to find duplicate values in all dictionaries by value?
You can find duplicate values with their occurrences using LINQ.
It gives you duplicate values and its occurrences (index in list and key in dictionary).
var duplicates = dicList
.SelectMany((x, i) => x.Select(p => new { Index = i, Key = p.Key, Value = p.Value }))
.GroupBy(x => x.Value)
.Where(x => x.Count() > 1)
.Select(x => new
{
Value = x.First().Value,
Occurrences = x.Select(o => new { Index = o.Index, Key = o.Key })
});
If you just want duplicate values then use simplified version
var duplicates = listOfDic
.SelectMany(x => x.Values)
.GroupBy(x => x)
.Where(x => x.Count() > 1);
Old classic loop
var uniqueValues = new HashSet<object>();
var duplicateValues = new List<object>();
foreach (var value in yourDictionaries.SelectMany(dict => dict.Values))
{
if (uniqueValues.Add(value) == false)
{
duplicateValues.Add(value);
}
}
SelectMany is a key method for getting all values of all dictionaries.
If you are fan of LINQ you can convert it to the LINQ expression for example by using Aggregate or GroupBy
Use linq for compact code:
List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
list.SelectMany(dictionary => dictionary.Values).GroupBy(d => d).Where(x => x.Count() >1);

c# - index of array entries inside another array using LINQ

I have an array of strings:
string[] stringArray = {"aaa", "bbb", "ccc", "aaa", "ccc", "ddd"};
I would like to get all indexes of this array where a substring of these strings are inside another array:
string[] searchArray = {"a","b"};
The answer I would like to get is then:
index = {0,1,3};
A soultion for just one entry of the searchArray would be:
List<int> index = stringArray.Select((s, i) => new { i, s })
.Where(t => t.s.Contains(searchArray[1]))
.Select(t => t.i)
.ToList();
A solution for all entries would be:
List<int> index = new List<int>();
foreach (string str in searchArray)
index.AddRange(stringArray.Select((s, i) => new { i, s })
.Where(t => t.s.Contains(str))
.Select(t => t.i)
.ToList());
index.Sort();
But out of curiosity, are there any solutions by just using one command in LINQ?
Yup, you just need Any to see if "any" of the target strings are contained in the array element:
List<int> index = stringArray
.Select((Value, Index) => new { Value, Index })
.Where(pair => searchArray.Any(target => pair.Value.Contains(target)))
.Select(pair => pair.Index)
.ToList();

How to convert IEnumerable<IEnumerable<IGrouping<int,string>>> to IEnumerable<IEnumerable<string>>

I'm trying to partition some comma separated lines into groups of size 2 at max.
How can i convert the collection of groups to list of lists as below?
I expect the partitions to be 3 first and then 4 after grouping.
List<string> chunk = new List<string>()
{
"a,b,c",
"a,d,e",
"b,c,d",
"b,e,d",
"b,f,g",
"e"
};
var partitons = chunk.GroupBy(c => c.Split(',')[0], (key, g) => g);
var groups = partitons.Select(x => x.Select((i, index) => new { i, index }).GroupBy(g => g.index / 2, e => e.i));
IEnumerable<IEnumerable<string>> parts = groups.Select(???)
This is what I wanted
var parts = groups.SelectMany(x => x).Select(y => y.Select(z => z));
Try this:
partitons = groups.Select(x => x.SelectMany(y => y));
I get this:

How to compare 2 list by characters content and its correspondents double values?

I have 2 lists: a string list and a double list with same length and with same index of correspondence. I need to compare all the strings, find the indexes of the list that has the same characters, independent of its order, and delete the highest double value that corresponds to both,
Example:
List<string> str= new List<string>();
str.add("efc");
str.add("abc");
str.add("cde");
str.add("cab");
str.add("fbc");
List<double> vlr= new List<double>();
vlr.add(0.1);
vlr.add(0.5);
vlr.add(0.4);
vlr.add(0.2);
vlr.add(0.3);
and this case, "abc" => (0.5) must be deleted because "cab" has the same characters AND lower correspondent value =>(0.2).
There is a lambda expression for this 2 arrays??
What I've tried:
var distinct = list .Select((str, idx) => new { Str = str, Idx = idx })
.GroupBy(pair => new HashSet<char>(pair.Str), HashSet<char>.CreateSetComparer())
.Select(grp => grp.OrderBy(p => p.Idx).First())
.ToList();
Here's one way to solve it:
// Pair the strings with their correspondence values
var pairs = str.Zip(vlr, (s, d) => new {s, d});
// Group using a sorted string, eliminating differences due to character order
var groups = pairs.GroupBy(x => new string(x.s.ToCharArray().OrderBy(c => c).ToArray()));
// For each group, retain the item with the lowest correspondence value
var filtered = groups.Select(x => x.OrderBy(y => y.d).First().s);
var newDict = str.Zip(vlr, (s, d) => new { s, d })
.GroupBy(x => String.Join("", x.s.OrderBy(y => y)))
.Select(g => g.OrderBy(x => x.d).First())
.ToDictionary(x => x.s, x => x.d);
here is the code:
var group = str.GroupBy(s => string.Join("", s.ToCharArray().OrderBy(c => c)));
var _vlr = group.Select(g => g.Min(s => vlr[str.IndexOf(s)]));
var _str = group.Select(g => g.OrderBy(s => vlr[str.IndexOf(s)]).First());
and the result:

Categories