Different kind of concatenate two arrays in c# - c#

I have two lists posted from view to controller such as
int[] blablaIds = { 13, 377, 1002 };
int[] secondBlaBlaIds = { 7, 18, 126 };
For some reason I want to explicitly combine these as
int[] combinedIds = { { 7, 13 }, {18, 377}, {126, 1002} }
Is it possible with LINQ?

There's no such thing as a list of long or int you're going to have to pick one and then convert the other list to the correct datatype. Once they're the same datatype you can easily concat the two lists.
longIds.Concat(intIds.Cast<long>());
As Jon Skeet has identified in the comments your question is incredibly difficult to answer in its current form. If you're looking to create a paired list of items from the first and second you could try using .Zip. You're still going to have to do some casting if you want ints and longs to coexist in the same collection. Here's an example (not verified with IDE).
var zipped = firstIds.Zip(secondIds, (first, second) => new List<long> {first, (long) second});

Have a look at SelectMany. It's rather powerful and should provide the functionality you are looking for.

Related

Get array consisting of first values of a list of tuples

In my C# code I have a list of Tuples. The tuples themselves consist of two numbers of the type double and an object of type LocalDate.
List<Tuple<double, double, LocalDate>> tupleList = new List<Tuple<double, double, LocalDate>>();
The list, for instance, could look as follows.
1, 10, LocalDate1
12, 310, LocalDate2
31, 110, LocalDate3
What is an elegant way to create an array of doubles that only contains the first double values of each list item?
Accordingly, I want an ArrayList that only consists of the LocalDate objects in the list. The order should be preserved.
The expected result should be:
double[] => [1, 12, 31]
double[] => [10, 310, 110]
ArrayList<> => [LocalDate1, LocalDate2, LocalDate3]
I am aware that the ordinary way would be to iterate over the list in a for loop and create the arrays via this loop. However, I think that there should be a more concise and elegant way.
Linq would be the way to go:
var firstValues = tupleList.Select(x => x.Item1).ToList();
This projects the list of Tuples into a list of the first items only, keeping their order. Same with the second, third, n'th item as well.
If you want an array, just invoke ToArray() instead of ToList().
This can be done with a baseline for loop:
//Sorry for any Syntax errors. Got no VS installation in reach
double[] output = new double[tupleList.Length];
for(int i = 0; i < tupleList.Length; i++){
output[i] = tupleList[i].Item1;
}
Of course something like linq or anything that uses lambdas in general might be more modern. But I doubt it is faster or more memory efficient. It has to use a List of some sort and create an array from that.

Binary Search on the first element in a multiple dimensional array

My goal is to perform a binary search for only the first element in a 2D array. I have been searching all day to find if it is possible using BinarySearch() in .NET but I can't find a thing.
To make this clearer. Imagine I had a 1D array, unsorted. If I sort the array, I lose the original index. I would like to create a second element of my array to hold the original index (this I can do) then sort by first element, then binary search over the first elements.
If anyone could push me in the right direction I'd be very grateful.
Thanks
Well, if I understand you correctly, you need something like this:
// initialize the array and the indexes array
var a2D = new int[2][];
a2D[0] = new[] { 3, 14, 15, 92, 65, 35 }; // <-- your array (fake data here)
a2D[1] = Enumerable.Range(0, a2D[0].Length).ToArray(); // create the indexes row
// sort the first row and the second one containing the indexes
Array.Sort(a2D[0], a2D[1]);
// now a2D array contains:
// row 0: 3, 14, 15, 35, 65, 92
// row 1: 0, 1, 2, 5, 4, 3
// and you can perform binary search on the first row:
int columnIndexOf35 = Array.BinarySearch(a2D[0], 35);
// columnIndexOf35 = 3
//
// a2D[0][columnIndexOf35] = 35 <- value
// a2D[1][columnIndexOf35] = 5 <- original index
As per MSDN, Array.BinarySearch method operates only with one-dimensional arrays, so it is impossible to use it directly in your case. Some of the options you have are:
Extract first column into a separate array and call Array.BinarySearch on it.
Define custom class Pair that implements interface IComparable and construct your array with the instances of this class.
Implement binary search on two dimensional array by yourself.
It looks like you want to have object that holds data and "original index" and than sort/search array of objects by data.
(This answer shows Andrei's option 2)
class IndexedData:IComparable
{
public MyType Data;
public int OriginalIndex;
public int CompareTo(object obj) {
// add correct checks for null,.. here
// and return correct comparison result.
// I.e. if MyType is IComparable - just delegate.
return Data.CompareTo(obj);
}
Check IComparable on MSDN for implementation/usage details.
Depending on what you're planning to do with the arrays afterwards, another solution might be to use LINQ.
var unsortedStartingArray = new[] {3, 6, 2, 1, 20, 20};
var q = unsortedStartingArray
.Select((item, index) => new {item, index})
.ToLookup(x => x.item, x => x.index);
var notFound = q[30]; // An empty array. Nothing found
var indexOf1 = q[1].First(); // returns 3
var multipleIndexsOf20 = q[20]; // Returns an array with 4, 5
The index into the lookup would then be the value you're searching for. Performance wise I would guesstimate this to be faster aswell about 5 times slower from my crude testing.

Get array index values of the top 1000 largest entries inside an array using LINQ

I would like to have a nice clean LINQ code that can get an array of the index values of the top 1000 largest values inside an array.
For example:
int[] IndexArray = ArrayWithValues.Return_Indexes_Of_1000_Biggest_Values
The code is obviously bogus it is just to illustrate what I need.
UPDATE
I totally forgot to say that I need a second functionality. I have a second array, and I need to retrieve all the values in the second array which has the same indexes as contained inside the IndexArray.
I can do it easily using loops and all that but the code is big, and I want to learn to use LINQ more often but at the moment LINQ is still very foreign to me.
I have gone through similar questions asked here but I was not able to modify the code to suite my needs, since people usually only need the values and not the indexes of the values.
Thanks for the help!
Something like this should work. It uses the overload of Select that allows you to incorporate a second input that is the index of the item in the sequence.
var indexArray = sourceArray
.Select((value, index) => new { value, index })
.OrderByDescending(item => item.value)
.Take(1000)
.Select(item => item.index)
.ToArray();
Simply project the value and index into an object, order by the value, take the top 1000 items, and then select simply the indexes before converting to an array.
Testing by taking the top 5 indexes from the array { 10, 4, 6, 8, 2, 3, 5, 1, 9, 7 } yields { 0, 8, 3, 9, 2 }, which maps to values { 10, 9, 8, 7, 6 }.
As the comments have already addressed in regards to your update, you can simply take these indices to select from the other if you are confident the arrays are equal in length or will otherwise not result in an IndexOutOfBoundsException.
.Select(item => otherArray[item.index])
.ToArray();
Another method you could look up would be Enumerable.Zip.

problem in using Distinct with Linq

Hi have an issue with Linq. I have an array of double values with duplicate entries. I want to extract only distinct values from it. I have the following code which doesn't work correctly.
double[] dIds = GetIds(); //dIds has more than 10,000 items
var itemIdCollection = from id in dIds.Distinct()
select id;
Console.WriteLine(itemIdCollection.count().ToString()); //count is just 2 !!!!
Can you please give me a solution on this?
Thank you,
First off, you don't have to do that freaky select. Just call dIds.Distinct(). Second, I can guarantee you that it works on any array of doubles. Your doubles are NOT different from everybody else's doubles.
Obviously, if Distinct() is returning an enumerable of a count of 2 (btw, Console.WriteLine(itemIdCollection.Count()) is sufficient) it is because GetIds() returns an array containing only two distinct doubles.
Your assumptions, they are incorrect.
Try this:
List<double> x = new List<double>()
{
3, 4, 5, 6, 7, 7, 7, 8, 8
};
List<double> distinct = x.Distinct().ToList();
distinct.ForEach(y => Console.WriteLine(y));
Console.ReadKey();
Ghost debugging attempt:
Are you generating new random IDs in your GetIds() function? If so, remember you should be instantiating Random outside the function...

C# algorithm - find least number of objects necessary

Let's say I have the following code.
var numberToGetTo = 60;
var list = new[] {10, 20, 30, 40, 50};
I want to be able to return 50 & 10 from list to = 60.
If the numberToGetTo was 100 I would want to return 50, 50.
If the numberToGetTo was 85 I would want to return 50, 40.
I want to return the least amount of numbers from the list necessary to get to the "numberToGetTo", while staying closest (equal or greather) than to it.
Is doing something like this with Linq possible?
This is an NP-complete problem called the knapsack problem. That means, that your best method is not going to be in polynomial time. You may have to brute-force a solution.
Here's an implementation that uses Linq to be as clean as possible. It makes no attempt to optimize for performance over large inputs.
I'm assuming that you wouldn't use this algorithm for large inputs anyway, since the problem is NP-Complete, and therefore clarity is the right goal. My algorithm is O(n^2), and recursive at that.
static IEnumerable<int> Knapsack(IEnumerable<int> items, int goal)
{
var matches = from i in items
where i <= goal
let ia = new[] {i}
select i == goal ? ia : Knapsack(items, goal - i).Concat(ia);
return matches.OrderBy(x => x.Count()).First();
}
This problem as currently stated is actually trivial. The easiest way to to get "equal or greater" than the target is to find the largest number A in the list, and stick it in the answer list N times, where N is the lowest N such that N * A > target.
I suspect this is not what the original poster really wants however. If the problem is restated to somehow measure the "closeness" of various answers, and make a distinction as to whether answers that are "closer" or answers that have less numbers are "better" then it becomes tougher. For example, if the target is 100, is an answer of [55,55] better or worse than an answer of [20,20,20,20,20] ?
Knapsack Problem, this may give you a clue.
http://en.wikipedia.org/wiki/Knapsack_problem
I'd say that you could create a lambda expression containing the actual alogrithm, but you'll need to use C#. Using 'just linq' will not be enough.
This sounds similar to the Subset sum problem, which can be solved in a reasonable amount of time for smallish sets using dynamic programming. It's not an easy or common problem, so you won't find a helpful Linq extension method for it :)
I just hacked this together and I'm sure someone could improve. But does something like this work?
public class App
{
static void Main(string[] eventArgs)
{
var list = new[] {10, 20, 30, 40, 50};
var whatYouNeed = GetWhatYouNeed(list, 60, 60);
//what you need will contain 50 & 10
//whatYouNeed = GetWhatYouNeed(list, 105,105);
//what you need will contain (50,50, 10)
}
private static IList<int> _whatYouNeed = new List<int>();
static IEnumerable<int> GetWhatYouNeed(IEnumerable<int> list, int goal, int amountRequired)
{ //this will make sure 20 is taken over 10, if the goal is 15. highest wins
var intYouNeed = list.OrderBy(x => Math.Abs(amountRequired - x)).FirstOrDefault(x => x > amountRequired);
if (intYouNeed == 0) intYouNeed = list.OrderBy(x => Math.Abs(amountRequired - x)).FirstOrDefault();
_whatYouNeed.Add(intYouNeed);
if (_whatYouNeed.Sum() < goal)
{
int howMuchMoreDoYouNeed = goal - _whatYouNeed.Sum();
GetWhatYouNeed(list, goal, howMuchMoreDoYouNeed);
}
return _whatYouNeed;
}
}
I was a bit lazy passing in two values to GetWhatYouNeed but you get the point.

Categories

Resources