Divide single Value for a many in table C# - c#

From
int BinaryTable = new int[] { 1101 };
To
int BinaryTable = new int[] { 1,1,0,1 };
Don't know how to change it right.

int[] BinaryTable = new int[] { 1101 };
List<int[]> allItems = new List<int[]>();
foreach (var item in BinaryTable)
{
var items = item.ToString().Select(y => int.Parse(y.ToString())).ToArray();
allItems.Add(items);
}
var final = allItems.SelectMany(x => x).ToArray();

You could do it this way:
var bits = BinaryTable.Select(b =>
b.ToString().
Select(r => r == '0' ? 0 : 1))
.SelectMany(x => x);
This works if you want to get from
[1101,11] → [1,1,0,1,1,1]
. It is not really clear what exact do you want. And this solution doesn't check that your input really contains only 1 and 0 digits, since it is integer it could theoretically contain every number.

Quick and dirty LINQ:
int value = 1101; // a bit strange representation
int[] BinaryTable = value
.ToString()
.Select(c => c - '0')
.ToArray();
Or since 13 == 1101 binary:
int value = 13; // just an integer
int[] BinaryTable = Convert.ToString(value, 2)
.Select(c => c - '0')
.ToArray();
In case you want convert one array into another array, use SelectMany instead of Select:
int[] source = new int[] {1101};
int[] BinaryTable = source
.SelectMany(value => value.ToString()
.Select(c => c - '0'))
.ToArray();
Or
int[] source = new int[] {13};
int[] BinaryTable = source
.SelectMany(value => Convert
.ToString(value, 2)
.Select(c => c - '0'))
.ToArray();

Related

Longest repeating sequence using linq only

As the title says i have a task to find the longest repeating sequence in a string and it has to be done with linq only - no ifs, no loop, no try, assignment is only allowed on initialization of variables, recursion is allowed. I've found the solution online and i understand what is happening but i can't transform it to linq -I'm not that familiar with it. I would greatly appreciate if someone could help me. Here is a link to what ive found -https://www.javatpoint.com/program-to-find-longest-repeating-sequence-in-a-string.
List<int> a = new List<int> {1, 2, 1, 2, 1, 2, 3, 2, 1, 2};
List<List<int>> aa = new List<List<int>>();
outerLoop(a);
var max = aa.Max(x => x.Count);
var m = from v in aa
where v.Count == max
select v;
m.Dump();
void outerLoop(List<int> list)
{
List<int> f = new List<int>();
f.AddRange(list.Skip(list.Count-1).Take(list.Count).ToList());
innerLoop(list, list.Skip(1).Take(list.Count).ToList());
f.ForEach(k => outerLoop(list.Skip(1).Take(list.Count).ToList()));
}
void innerLoop(List<int> l, List<int> subList)
{
List<int> f = new List<int>();
f.AddRange(subList.Skip(subList.Count-1).Take(subList.Count).ToList());
var tt = l.TakeWhile((ch, i) => i < subList.Count && subList[i] == ch).ToList();
aa.Add(tt);
f.ForEach(k => innerLoop(l, subList.Skip(1).Take(subList.Count).ToList()));
}
so i came up with this "beauty", i don't think it's good code but i think it works. If anyone is interested and wants to make suggestions how to make it better, they are more than welcome to :)
if input is int[] x= {1, 2, 1, 2, 1, 2, 3, 2, 1, 2}
result should be 1212
Give this a go:
List<int> words = new List<int> { 1, 2, 1, 2, 1, 2, 3, 2, 1, 2 };
string result =
words
.Select((c, i) => i)
.SelectMany(i => Enumerable.Range(1, words.Count - i).Select(j => words.Skip(i).Take(j)), (i, w) => new { i, w })
.GroupBy(x => String.Join(",", x.w), x => x.i)
.Where(x => x.Skip(1).Any())
.Select(x => x.Key)
.OrderByDescending(x => x.Length)
.First();
That gives me 1,2,1,2.
If you want one that actually works with strings, try this:
var word = "supercalifragilisticexpialidocious";
string result =
word
.Select((c, i) => i)
.SelectMany(i => Enumerable.Range(1, word.Length - i).Select(j => word.Skip(i).Take(j)), (i, w) => new { i, w })
.GroupBy(x => new string(x.w.ToArray()), x => x.i)
.Where(x => x.Skip(1).Any())
.Select(x => x.Key)
.OrderByDescending(x => x.Length)
.First();
That gives me ali.
Here's a slightly more understandable version:
var word = "supercalifragilisticexpialidocious";
string result =
(
from i in Enumerable.Range(0, word.Length)
from j in Enumerable.Range(1, word.Length - i)
group i by word.Substring(i, j) into gis
where gis.Skip(1).Any()
orderby gis.Key.Length descending
select gis.Key
).First();
Here is my version. It isn't a single LINQ expression, but does use only LINQ. It does return all same length subsequences if there are multiple answers. It should work any type of sequence. It was written to only use standard LINQ methods.
It uses GroupBy with a string key to implement a sequence Distinct. (Because of this trick, lists that contain items with commas might not work right.) In production code, I would use a Distinct with an IEqualityComparer for sequences based on SequenceEqual. It also has a separate step for finding the maximum repeated sequence length and then finding all the matching sequences, in production code I would use a MaxBy extension.
Update: Since I was using GroupBy for DistinctBy, I realized I could just use that to count the subsequence repeats directly rather than search for them.
var repeaters = Enumerable.Range(0, words.Count) // starting positions
.SelectMany(n => Enumerable.Range(1, (words.Count - n) / 2).Select(l => words.Skip(n).Take(l).ToList())) // subseqs from each starting position
.GroupBy(s => String.Join(",", s), (k, sg) => new { seq = sg.First(), Repeats = sg.Count() }) // count each sequence
.Where(sr => sr.Repeats > 1) // only keep repeated sequences
.Select(sr => sr.seq); // no longer need counts
var maxRepeaterLen = repeaters.Select(ss => ss.Count()).Max(); // find longest repeated sequence's length
var maxLenRepeaters = repeaters.Where(ss => ss.Count() == maxRepeaterLen); // return all sequences matching longest length

How to convert a multi-dimensional array to a dictionary?

I have a n-by-3 array I wish to convert to a Dictionary<string,string[]> where the first column is the key and the rest of the column as an array for the value.
For example:
Key = arr[0,0], Value = new string[2] {arr[0,1], arr[0,2]}.
I'm aware of ToDictionary but I don't know how to set the value part.
arr.ToDictionary(x=>arr[x,0],x=>new string[2]{arr[x,1],arr[x,2]});
//This doesn't work!!!
How can I set it up correctly?
Multidimensional arrays are a continuous block of memory, so you kind of have to treat them like a single array. Try this:
var dict = arr.Cast<string>()
.Select((s, i) => new { s, i })
.GroupBy(s => s.i / arr.GetLength(1))
.ToDictionary(
g => g.First().s,
g => g.Skip(1).Select(i => i.s).ToArray()
);
With explanations:
// First, cast it to an IEnumerable<string>
var dict = arr.Cast<string>()
// Use the Select overload that lets us get the index of the element,
// And we capture the element's index (i), along with the element itself (s)
// and put them together into an anonymous type [1]
.Select((s, i) => new { s, i })
// .GetLength(dimension) is a method on multidimensional arrays to
// get the length of a given dimension (pretty self-explanatory)
// In this case, we want the second dimension, or how wide each
// row is: [x,y] <- we want y
// Divide the element index (s.i) by that length to get the row index
// for that element
.GroupBy(s => s.i / arr.GetLength(1))
// Now we have an Grouping<int, IEnumerable<anonymous{string,int}>>
.ToDictionary(
// We don't care about the key, since it's the row index, what we want
// is the string value (the `s` property) from first element in the row
g => g.First().s,
// For the value, we want to skip the first element, and extract
// the string values (the `s` property), and then convert to an array
g => g.Skip(1).Select(i => i.s).ToArray()
);
[1]: See here for documentation on anonymous types.
Sometimes not using linq is easier to read and faster:
var dict = new Dictionary<string, string[]>();
for (int i = 0; i < arr.GetLength(0); i++)
dict[arr[i, 0]] = new string[] { arr[i, 1], arr[i, 2] };
But when you feel like you REALLY need to use linq:
Enumerable.Range(0, arr.GetLength(0))
.ToDictionary(i => arr[i, 0], i => new string[] {arr[i, 1], arr[i, 2]});
This is the simplest approach I can come up with:
var arr = new int[4, 3]
{
{ 1, 2, 3 },
{ 3, 5, 7 },
{ 5, 8, 11 },
{ 7, 11, 15 },
};
var dict = arr.Cast<int>().Buffer(3).ToDictionary(x => x[0], x => x.Skip(1).ToArray());
That gives me:
You just need to NuGet "System.Interactive" to get the Buffer operator.
Or use this implementation:
public static IEnumerable<T[]> Buffer<T>(this IEnumerable<T> source, int count)
=>
source
.Select((t, i) => new { t, i })
.GroupBy(x => x.i / count)
.Select(x => x.Select(y => y.t).ToArray());
I guess your approach was right ,my only doubt is that your array is static or not?
arr.Select((value, index) => new { value, index }) .ToDictionary(x => x.index, x => new string[2]{x.value[x.index][1],x.value[x.index][2]}));
Note: I couldn't execute and check the code ! Sorry.
I had done using Integer. Please Change for your requirements.
public static void Main()
{
int row=0 , col=0;
int[,] array = new int[,]
{
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 },
{ 10, 11, 12 }
};
int flag=0;
for (int i = 0; i < array.Rank; i++)
{
if(flag==0)
{
row= array.GetLength(i);
flag=1;
}
else
{
col= array.GetLength(i);
}
}
Dictionary<int,int[,]> dictionary = new Dictionary<int, int[,]>();
for(int i=0;i<row;i++)
{
dictionary.Add(array[i,0],new int[, ]{{array[i,1]},{array[i,2]}});
}
Console.WriteLine(dictionary[4].GetValue(0,0));
}

get indexes of different elements from arrays with equal length using Linq

I have two arrays with same length. for example
arr1 {1,2,3,4,5,6,7,8,9,0}.
arr2 {1,2,5,3,4,6,7,1,1,0}.
I need to get indexes of elements which are different:
{2,3,4,7,8}
How to do this using Linq?
The simplest I could think of:
int[] diff = Enumerable.Range(0, arr1.Length).Where(i => arr1[i] != arr2[i]).ToArray();
This should work:
int[] arr1 = new[] {1,2,3,4,5,6,7,8,9,0};
int[] arr2 = new[] {1,2,5,3,4,6,7,1,1,0};
var differentIndexes = arr2.Select((item, index) => new { item, index })
.Where(x => x.item != arr1[x.index])
.Select(x => x.index)
.ToArray();
You could use Enumerable.Zip() to walk the arrays in parallel, compare the values, then output matching sequence indices:
int [] arr1 = new int [] {1,2,3,4,5,6,7,8,9,0};
int [] arr2 = new int [] {1,2,5,3,4,6,7,1,1,0};
var query = arr1.Zip(arr2, (i, j) => i != j).Select((b, i) => b ? (int?)i : null).Where(iptr => iptr.HasValue).Select(iptr => (int)iptr);
Debug.WriteLine(JsonConvert.SerializeObject(query.ToList())); // outputs [2,3,4,7,8]
This doesn't require the sequences to be arrays.

Grouping the elements of an Array with the help of a bin Array

Assume that we have an array:
int[] values = new int[10];
values[0] = 1;
values[1] = 2;
values[2] = 3;
values[3] = 4;
values[4] = 6;
values[5] = 8;
values[6] = 2;
values[7] = 1;
values[8] = 3;
values[9] = 9;
And I have another array, say, the def array that defines the buckets:
int[] def= new int[3]; // defs holds the definition of the buckets
def[0] = 0;
def[1] = 5;
def2] = 10;
I want to use this def array to group the values array, in order to get the frequency distribution, using c#:
i.e.
bin[0] = 7; // the number of array values that lies between 0 and 5
bin[1] = 3; // the number of array values that lies between 5 and 10
I already found a solution with loops, but I am sure there is more elegant and neater way to do this operation; the linq / group by method.
How can I code this procedure using LINQ Group By?
Thanks in advance for anyone contributing to the answer,
Aykut
If I've understood you correctly, then you're looking something like this:
var array = new[] { 1, 2, 3, 4, 6, 8, 2, 1, 3, 9 };
var buckets = new[] { 0, 5, 10 };
var distributionFreq = buckets
.Skip(1) // we don't need the first bucket
.OrderBy(bucket => bucket) // just ensure, that buckets are ordered properly
.Select((bucket, i) => new
{
Min = buckets[i], // minimal value of range
Max = bucket // maximal value of range
})
.Select(range => new
{
Range = range,
NumberOfValuesAtRange = array.Count(item => item > range.Min && item < range.Max)
})
.ToArray();
First, you have to define the range of values (0..5, 5..10, and so on).
Second, count the number of values in source array, which fits the range.
Note, that you should define more precisely the criteria for the outermost values, e.g. does the value of 5 fits the first range, or the second one?
Try this:
var bin =
array
.GroupBy(x => x / 5)
.Select(x => x.Count())
.ToArray();
Or better yet this:
var lookup = array.ToLookup(x => x / 5);
var bin =
Enumerable
.Range(0, lookup.Max(x => x.Key) + 1)
.Select(x => lookup[x].Count())
.ToArray();
This second example works if there are some outlying numbers in the original array.
Or even better, using buckets:
var buckets = new [] { 0, 5, 10, };
var lookup = array.ToLookup(x => buckets.Where(b => x >= b).Count() - 1);
var bin =
Enumerable
.Range(0, lookup.Max(x => x.Key) + 1)
.Select(x => lookup[x].Count())
.ToArray();

Convert string[] to int[] in one line of code using LINQ

I have an array of integers in string form:
var arr = new string[] { "1", "2", "3", "4" };
I need to an array of 'real' integers to push it further:
void Foo(int[] arr) { .. }
I tried to cast int and it of course failed:
Foo(arr.Cast<int>.ToArray());
I can do next:
var list = new List<int>(arr.Length);
arr.ForEach(i => list.Add(Int32.Parse(i))); // maybe Convert.ToInt32() is better?
Foo(list.ToArray());
or
var list = new List<int>(arr.Length);
arr.ForEach(i =>
{
int j;
if (Int32.TryParse(i, out j)) // TryParse is faster, yeah
{
list.Add(j);
}
}
Foo(list.ToArray());
but both looks ugly.
Is there any other ways to complete the task?
Given an array you can use the Array.ConvertAll method:
int[] myInts = Array.ConvertAll(arr, s => int.Parse(s));
Thanks to Marc Gravell for pointing out that the lambda can be omitted, yielding a shorter version shown below:
int[] myInts = Array.ConvertAll(arr, int.Parse);
A LINQ solution is similar, except you would need the extra ToArray call to get an array:
int[] myInts = arr.Select(int.Parse).ToArray();
EDIT: to convert to array
int[] asIntegers = arr.Select(s => int.Parse(s)).ToArray();
This should do the trick:
var asIntegers = arr.Select(s => int.Parse(s));
To avoid exceptions with .Parse, here are some .TryParse alternatives.
To use only the elements that can be parsed:
string[] arr = { null, " ", " 1 ", " 002 ", "3.0" };
int i = 0;
var a = (from s in arr where int.TryParse(s, out i) select i).ToArray(); // a = { 1, 2 }
or
var a = arr.SelectMany(s => int.TryParse(s, out i) ? new[] { i } : new int[0]).ToArray();
Alternatives using 0 for the elements that can't be parsed:
int i;
var a = Array.ConvertAll(arr, s => int.TryParse(s, out i) ? i : 0); //a = { 0, 0, 1, 2, 0 }
or
var a = arr.Select((s, i) => int.TryParse(s, out i) ? i : 0).ToArray();
C# 7.0:
var a = Array.ConvertAll(arr, s => int.TryParse(s, out var i) ? i : 0);
you can simply cast a string array to int array by:
var converted = arr.Select(int.Parse)
var asIntegers = arr.Select(s => int.Parse(s)).ToArray();
Have to make sure you are not getting an IEnumerable<int> as a return
var list = arr.Select(i => Int32.Parse(i));

Categories