How can i compare two Lists ? <long[]> and <int> indexs - c#

This is the code:
var numbers =
lightningsRegions.SelectMany(
s => Regex.Matches(s, #"\[(\d+)[ -]+(\d+)\]")
.Cast<Match>()
.Select(m => m.Groups.Cast<Group>().Skip(1).Select(x => x.Value)
.ToArray())
.Select(x => new { start = int.Parse(x[0]), end = int.Parse(x[1]) })
.SelectMany(x => Enumerable.Range(x.start, x.end - x.start + 1))
)
.ToList();
for (int i = 0; i < list_of_histogramsR.Count ; i++)
{
if (list_of_histogramsR[i] == numbers[i])
{
}
}
I consider the variable numbers as number of indexs. In the end numbers contain 5372 numbers.
So each number from thr 5272 is like an index.
Now i have this List<long[]> list_of_histogramsR wich contain 16595 indexs.
I want to check that if any number from numbers is in list_of_histogramsR as index number then do something.
For example the first number in numbers is 41. So when index number 41 of list_of_histogramsR == to the number 41 in numbers do something. Then the same for the next numbers in the variable numbers.
The problem is that on the IF line im getting error: Error 33 Operator '==' cannot be applied to operands of type 'long[]' and 'int'
Why ?

You can use Contains to check if the list contains a specific number (cast the int to a long):
list_of_histogramsR[i].Contains((long)numbers[i])

Related

sorting number based on the similar starting digits

I have a var allList which contains a list of all the accounts in my tables , I want to order the account ids based on the parent number which the first three digits or four digits, if string have similar starting digits can be next to that,
I have the following data as the output per now
101
202
303
404
10111
10122
20211
20222
303211
101112
101222
10111221
42215
10111223
3035422525
1011122121
I want the output to be like this
101
10111
10122
101112
101222
10111221
10111223
1011122121
202
20211
2022222
2023221
303
303211
3035422525
404
42215
I have tried this code, the accountid is string,can we use thenby or trimstrat
allList = allList.OrderBy(x => x.accountId);
It seems that you want something like this:
allList = allList
.OrderBy(item => item.Length <= 3 ? item : item.Substring(0, 3))
.ThenBy(item => item.Length)
.ThenBy(item => item)
.ToList();
Here we sort
By first 3 digits ("first three digits or four digits"): 101 < 404
On tie, by Length: 10122 < 101112
On tie, by items lexicographically: 10111221 < 10111223

Split array into subarrays of specific length

I know that similar questions were asked many times. However I didn't find solution which I need and also cannot find out it myself.
My scenario: I have array of bytes. Now I need to convert them into bits and then create array which will contains exact number of bits.
I am able to convert them into bits and create array of specific length, but only with 8 bits in every index.
My code example:
var blocks = byteArr.Select(byte => Convert.ToString(byte, 2).PadLeft(8, '0'))
.Select((byte, i) => new { Value = byte, Index = i })
.GroupBy(x => x.Index / 100)
.Select(grp => grp.Select(x => x.Value).ToArray())
.ToArray();
It returns array. How you see on the screenshot, it creates array of '100 byte arrays' but what I need is array of '100 bits arrays' or better array of strings where every string has 100 bits.
Thanks for reply and help.
Try the following
var blocks = byteArr.SelectMany(myByte => Convert.ToString(myByte , 2).PadLeft(8, '0'))
.Select((bit, i) => new { Bit = bit, Index = i })
.GroupBy(x => x.Index / 100)
.Select(grp => new string(grp.Select(x => x.Bit).ToArray()))
.ToArray();
The SelectMany will break your binary strings into the individual chars, then you'll group them into sets of 100 by the index. Finally you just create the new string of those "char bits".

LINQ non-linear order by string length

I'm trying to get a list of string ordered such that the longest are on either end of the list and the shortest are in the middle. For example:
A
BB
CCC
DDDD
EEEEE
FFFFFF
would get sorted as:
FFFFFF
DDDD
BB
A
CCC
EEEEE
EDIT: To clarify, I was specifically looking for a LINQ implementation to achieve the desired results because I wasn't sure how/if it was possible to do using LINQ.
You could create two ordered groups, then order the first group descending(already done) and the second group ascending:
var strings = new List<string> {
"A",
"BB",
"CCC",
"DDDD",
"EEEEE",
"FFFFFF"};
var two = strings.OrderByDescending(str => str.Length)
.Select((str, index) => new { str, index })
.GroupBy(x => x.index % 2)
.ToList(); // two groups, ToList to prevent double execution in following query
List<string> ordered = two.First()
.Concat(two.Last().OrderBy(x => x.str.Length))
.Select(x => x.str)
.ToList();
Result:
[0] "FFFFFF" string
[1] "DDDD" string
[2] "BB" string
[3] "A" string
[4] "CCC" string
[5] "EEEEE" string
Don't ask how and why... ^^
list.Sort(); // In case the list is not already sorted.
var length = list.Count;
var result = Enumerable.Range(0, length)
.Select(i => length - 1 - 2 * i)
.Select(i => list[Math.Abs(i - (i >> 31))])
.ToList();
Okay, before I forget how it works, here you go.
A list with 6 items for example has to be reordered to this; the longest string is at index 5, the shortest one at index 0 of the presorted list.
5 3 1 0 2 4
We start with Enumerable.Range(0, length) yielding
0 1 2 3 4 5
then we apply i => length - 1 - 2 * i yielding
5 3 1 -1 -3 -5
and we have the non-negative part correct. Now note that i >> 31 is an arithmetic left shift and will copy the sign bit into all bits. Therefore non-negative numbers yield 0 while negative numbers yield -1. That in turn means subtracting i >> 31 will not change non-negative numbers but add 1 to negative numbers yielding
5 3 1 0 -2 -4
and now we finally apply Math.Abs() and get
5 3 1 0 2 4
which is the desired result. It works similarly for lists of odd length.
Just another option, which I find more readable and easy to follow:
You have an ordered list:
var strings = new List<string> {
"A",
"BB",
"CCC",
"DDDD",
"EEEEE",
"FFFFFF"};
Create a new list and simply alternate where you add items::
var new_list = new List<string>(); // This will hold your results
bool start = true; // Insert at head or tail
foreach (var s in strings)
{
if (start)
new_list.Insert(0,s);
else
new_list.Add(s);
start = !start; // Flip the insert location
}
Sweet and simple :)
As for Daniel Bruckner comment, if you care about which strings comes first, you could also change the start condition to:
// This will make sure the longest strings is first
bool start= strings.Count()%2 == 1;

How to use Sum on array of strings - LINQ?

How to sum array of strings with LINQ Sum method?
I have string which looks like: "1,2,4,8,16"
I have tried:
string myString = "1,2,4,8,16";
int number = myString.Split(',').Sum((x,y)=> y += int.Parse(x));
But it says that cannot Parse source type int to type ?.
I do not want to use a foreach loop to sum this numbers.
You're mis-calling Sum().
Sum() takes a lambda that transforms a single element into a number:
.Sum(x => int.Parse(x))
Or, more simply,
.Sum(int.Parse)
This only works on the version 4 or later of the C# compiler (regardless of platform version)
Instead of
int number = myString.Split(',').Sum((x,y)=> y += int.Parse(x));
use
int number = myString.Split(',').Sum(x => int.Parse(x));
which will parse each element of myString.Split(',') to ints and add them.
var value = "1,2,4,8,16".Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select (str => int.Parse(str))
.Sum ( ) ;
Console.WriteLine( value ); // 31

LINQ Grouping by Sum Value

Say I have a class like so:
public class Work
{
public string Name;
public double Time;
public Work(string name, double time)
{
Name = name;
Time = time;
}
}
And I have a List<Work> with about 20 values that are all filled in:
List<Work> workToDo = new List<Work>();
// Populate workToDo
Is there any possible way that I can group workToDo into segments where each segments sum of Time is a particular value? Say workToDo has values like so:
Name | Time
A | 3.50
B | 2.75
C | 4.25
D | 2.50
E | 5.25
F | 3.75
If I want the sum of times to be 7, each segment or List<Work> should have a bunch of values where the sum of all the Times is 7 or close to it. Is this even remotely possible or is it just a stupid question/idea? I am using this code to separate workToDo into segments of 4:
var query = workToDo.Select(x => x.Time)
.Select((x, i) => new { Index = i, Value = x})
.GroupBy(y => y.Index / 4)
.ToList();
But I am not sure how to do it based on the Times.
Here's a query that segments your data in groups where the times are near to 7, but not over:
Func<List<Work>,int,int,double> sumOfRange = (list, start, end) => list
.Skip(start)
.TakeWhile ((x, index) => index <= end)
.ToList()
.Sum (l => l.Time);
double segmentSize = 7;
var result = Enumerable.Range(0, workToDo.Count ())
.Select (index => workToDo
.Skip(index)
.TakeWhile ((x,i) => sumOfRange(workToDo, index, i)
<= segmentSize));
The output for your example data set is:
A 3.5
B 2.75
total: 6.25
B 2.75
C 4.25
total: 7
C 4.25
D 2.5
total: 6.75
D 2.5
total: 2.5
E 5.25
total: 5.25
F 3.75
total: 3.75
If you want to allow a segments to total over seven, then you could increase the segmentSize variable by 25% or so (i.e. make it 8.75).
This solution recurses through all combinations and returns the ones whose sums are close enough to the target sum.
Here is the pretty front-end method that lets you specify the list of work, the target sum, and how close the sums must be:
public List<List<Work>> GetCombinations(List<Work> workList,
double targetSum,
double threshhold)
{
return GetCombinations(0,
new List<Work>(),
workList,
targetSum - threshhold,
targetSum + threshhold);
}
Here is the recursive method that does all of the work:
private List<List<Work>> GetCombinations(double currentSum,
List<Work> currentWorks,
List<Work> remainingWorks,
double minSum,
double maxSum)
{
// Filter out the works that would go over the maxSum.
var newRemainingWorks = remainingWorks.Where(x => currentSum + x.Time <= maxSum)
.ToList();
// Create the possible combinations by adding each newRemainingWork to the
// list of current works.
var sums = newRemainingWorks
.Select(x => new
{
Works = currentWorks.Concat(new [] { x }).ToList(),
Sum = currentSum + x.Time
})
.ToList();
// The initial combinations are the possible combinations that are
// within the sum range.
var combinations = sums.Where(x => x.Sum >= minSum).Select(x => x.Works);
// The additional combinations get determined in the recursive call.
var newCombinations = from index in Enumerable.Range(0, sums.Count)
from combo in GetCombinations
(
sums[index].Sum,
sums[index].Works,
newRemainingWorks.Skip(index + 1).ToList(),
minSum,
maxSum
)
select combo;
return combinations.Concat(newCombinations).ToList();
}
This line will get combinations that sum to 7 +/- 1:
GetCombinations(workToDo, 7, 1);
What you are describing is a packing problem (where the tasks are being packed into 7-hour containers). Whilst it would be possible to use LINQ syntax in a solution to this problem, there is no solution inherent in LINQ that I am aware of.

Categories