I have a list of strings, which contains information, which I want to save in separate variables.
The .txt file contains line with this kind of information:
1 kitchen 1 microwave microwave2 relevant 0.0025 1.29 0.88 1.29
var index = Enumerable.Range(2, 3).ToArray();
string objectInformationText = System.IO.File.ReadAllText("objectList.txt");
string[] objectInformation = objectInformationText.Split('\t');
Now, I want to extract items from objectInformation based on my index (i.e. item 2 and 3). The output should be a subset only containing items 2 and 3 from the list.
A solution can be using lambda Select function as follow:
var result = index.Select(x => information[x]).ToList();
While #OmG's answer is correct, the alternative for creating a temp collection of indexes in your case would be using Skip/Take linq selectors.
objectInformation.Skip(2).Take(3)
This will obviously work only for contiguous span of indexes.
In linQ there is a lot of way to select based on the index.
string input = "1 kitchen 1 microwave microwave2 relevant 0.0025 1.29 0.88 1.29";
var spt = input.Split(' ');
//Select everything after the 1 element:
var afterTitle = spt.Skip(1);
//Select from index 2 to 5 incuding them -> 1 microwave microwave2 relevant
var from2to5 = spt .Skip(2) // Skip index 0, 1
.Take(4); // Take 2,3,4,5
//Select based on a Index list, OmG's answer is a better alternative for this one.
int[] idx = { 1, 2, 4, 5 };
var inIdx = spt.Where((value,index)=> idx.Contains(index));
The last exemple will be usefull when the index needed could be calculated.
//Select only the Even one
var even = spt.Where((value,index)=> index%2==0);
Related
Let's say i have a inventory slot range from 1 to 100 how to find the first empty slot from the range?
First, i'm thinking of using Array.FindIndex but i'm stuck at here.
var InventorySlot = (from i in db.InventoryModel where i.userId == 1 select i.slot).ToArray();
int index = Array.FindIndex(InventorySlot, item => item == null );
But this will create
InventorySlot[0] = 1
InventorySlot[1] = 3
InventorySlot[2] = 4
So how to create like this?
InventorySlot[1] = x
InventorySlot[3] = x
InventorySlot[4] = x
Perhaps i can use Array.FindIndex to locate the empty array? The index variable i need is 2(First empty number in the array)
What you need to do is compare the result from the database with the range without exceptions:
var firstEmptySlot = Enumerable.Range(1, InventorySlot.Max()).Except(InventorySlot).First();
If you want to get the largest slot plus one if no slot is empty, you can do:
var firstEmptySlot = Enumerable.Range(1, InventorySlot.Max()+1).Except(InventorySlot).First();
You would need to test firstEmptySlot in this case to make sure it is <= 100.
You could combine testing and the query by limiting the range to 1 - 100:
var firstEmptySlot = Enumerable.Range(1, Math.Min(InventorySlot.Max()+1, 100)).Except(InventorySlot).FirstOrDefault();
You will get a 0 back if no empty slots from 1 - 100 are available.
Given two lists A and B:
A={6,16,22}
B={6,7,8,22,24,25}
I want to get:
1. the number of items that appear in both lists. (E.g. "2", because 6 and 22 from `A` are also in `B`.)
2. the number of items that are in `A` but not in `B`. (E.g. "1", because 16 is in `A` but not in `B`)
3.The number of items count adjacent numbers as 1 (E.g, A 6 is there B 6,7,8 is there so 6,7,8 count as 1 )
You can use Enumerable.Except and Enumerable.Intersect:
var aNotInB = a.Except(b);
int aNotInBCount = aNotInB.Count(); // 1 because 16 is not in second list
var aInB = a.Intersect(b);
int aInBCount = aInB.Count(); // 2 because 6,22 are in second list
What u want is here:
A.Except(B).Count();
Was hoping to find out if there is an easy way to check if a list only contains certain list values.
For example if I have a list of int that could randomly contain distinct ints 1-10 (ie 1,3,7 or 2,3,4,6,8,9) and I want to check if the list only contains int 1 and/or 5. 1 or 5 or 1,5 would return true and anything else would return false.
This is actually for an MVC project and is a list of strings. Based on conditions I build a string list and want to check if 1 or both of 2 certain strings but no other strings are present in the list.
For now I take the list and check if it contains each of the 2 strings and removes them if they exist. I then can count the list and if > 0 I know that 1 or both of the strings are not the only values in the list. This feels very hackish and I assume there is better way to do it. Also in the future if my two strings were instead another dynamic list of strings it would be nice to have a simple method rather than having to foreach each string of both lists to remove them from one if existing in another before I can count list to get the bool I need.
Was hoping there was something similar to .Contains(T Item) like .OnlyContains(T Item or IEnumerable) but haven't found anything like that yet.
Thanks.
if (someList.Except(desiredItems).Any())
// Uh oh
If i understood the question correctly you want to know if a collection contains any of the items in another collection. Use Enumerable.Intersect:
var ints1 = new[] { 1, 3, 7 };
var ints2 = new [] { 2, 3, 4, 6, 8, 9 };
var list = new[] { 1, 5 };
bool containsAny = ints1.Intersect(list).Any();
Console.WriteLine(containsAny); // True
containsAny = ints2.Intersect(list).Any();
Console.WriteLine(containsAny); // False
To include also this requirement
A list of 1,5 or a list with no elements would also return true.
Just check if the collection contains any elements:
bool any = list.Any();
What would be the most efficient way to select all the items in a specific range from a list and put it in a new one?
List<DataClass> xmlList = new List<DataClass>();
This is my List, and I would like to put all the DataClass items between the range (3 - 7) in a new List.
What would be the most efficient way? A foreach loop that that count++ everytime untill he reaches the items between a the range and add those items to the new list?
The method you are seeking is GetRange:
List<int> i = new List<int>();
List<int> sublist = i.GetRange(3, 4);
var filesToDelete = files.ToList().GetRange(2, files.Length - 2);
From the summary:
// Summary:
// Creates a shallow copy of a range of elements in the source System.Collections.Generic.List<T>.
// Parameters:
// index:
// The zero-based System.Collections.Generic.List<T> index at which the range
// starts.
// count:
// The number of elements in the range.
If for any reason you don't like to use the GetRange method, you could also write the following using LINQ.
List<int> list = ...
var subList = list.Skip(2).Take(5).ToList();
List implements a CopyTo method that lets you specify the start and number of elements to copy. I'd suggest using that.
See: http://msdn.microsoft.com/en-us/library/3eb2b9x8.aspx
in c# 8 you can use Range and Index instead of Linq take and skip for List
notice: before using you should convert the list to array
Sample array:
string[] CountryList = { "USA", "France", "Japan", "Korea", "Germany", "China", "Armenia"};
var countryArray = CountryList.ToArray();
To get this result (element 1,2,3) ==> France Japan Korea
1: Get a range of array or list:
var newArr = countryArray[1..3]
2: Define Range object
Range range = 1..3;
var newArr = countryArray[range])
3: Use Index Object
Index startIndex = 1;
Index endIndex = 3;
var newArr = countryArray[startIndex..endIndex]
Given two arrays, I need to extract values from arrayB based on where the range(actual values) falls in arrayA.
Index 0 1 2 3 4 5 6 7 8 9 10 11 12
-------------------------------------------------------------
ArrayA = {0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6}
ArrayB = {1, 0.2, 3, 4, 5, 6,5.5, 8, 9,11.1, 11, 12, 3}
Given the following ranges, I need to extract the following results
RangeToExtract* IndexInArrayA Expected Values To Extract
-------------- ------------- --------------------------
0 -> 1 [0,2] 1,0.2,3
1 -> 3 [3,6] 4,5,6,5.5
3 -> 5 [7,10] 5.5,8,9,11.1,11
1 -> 5 [3,10] 4,5,6,5.5,8,9,11.1,11
3 -> 10 [7,12] 8,9,11.1,11,12,3
* Refers to the actual values in ArrayA
Note: Given the RangeToExtract (0->1), determine the indexes in ArrayA where these values are, the result being (0->1) maps to [0,2] (The value 1 is in position 2 in ArrayA)
I only figured that the following special cases exists (not sure if there are more)
the lower limit is equal to zero and
when the upper limit does not exist in ArrayA
Further info:
Both arrays will be the same size
ArrayA will always be sorted
Code:
private double[] GetRange(double lower, double upper)
{
var myList = new double[ArrayA.Length];
var lowerIndex = Array.IndexOf(ArrayA, lower);
var upperIndex = Array.IndexOf(ArrayA, upper);
// special case 1
if (lowerIndex != 0)
{
lowerIndex = lowerIndex + 1;
}
// special case 2
if (upperIndex == -1)
{
upperIndex = ArrayA.Length-1;
}
for (int i = lowerIndex; i <= upperIndex; i++)
{
myList[i] = ArrayB[i];
}
return myList;
}
Given the above code, have all the special cases been taken into account? Is there a better way to write the above code?
Yap! There is a quite better way, that comes with lovely LINQ. I put here in two forms. First looks complicated but not at ALL! Believe me ;)
At the first step you have to take out those A'indexes that their values fall into your range (I call it min...max), based on your example I got that your range is closed from the lower boundary and closed on upper side, I means when you mentioned 3 -> 5 actually It is [3, 5)! It does not contain 5. Anyway that is not the matter.
This can be done by following LINQ
int[] selectedIndexes = a.Select((value, index) =>
new { Value = value, Index = index }).
Where(aToken => aToken.Value > min && aToken.Value <= max).
Select(t => t.Index).ToArray<int>();
The first select, generates a collection of [Value, Index] pairs that the first one is the array element and the second one is the index of the element within the array. I think this is the main trick for your question. So It provides you with this ability to work with the indexes same as usual values.
Finally in the second Select I just wrap whole indexes into an integer array. Hence after this you have the whole indexes that their value fall in the given range.
Now second step!
When you got those indexes, you have to select whole elements within the B under the selected Indexes from the A. The same thing should be done over the B. It means again we select B element into a collection of [Value, Index] pairs and then we select those guys that their indexes exist within the selected indexes from the A. This can be done as follow:
double[] selectedValues = b.Select((item, index) =>
new { Item = item, Index = index }).
Where(bToken => selectedIndexes.Contains(bToken.Index)).
Select(d => d.Item).ToArray<double>();
Ok, so first select is the one I talked about it in the fist part and then look at the where section that check whether the index of the bToken which is an element of B exists in the selectedIndexes (from A) or not!
Finally I wrap both codes into one as below:
double[] answers = b.Select((item, index) =>
new { Item = item, Index = index }).
Where(bTokent =>
a.Select((value, index) =>
new { Value = value, Index = index }).
Where(aToken => aToken.Value > min && aToken.Value <= max).
Select(t => t.Index).
Contains(bTokent.Index)).Select(d => d.Item).ToArray<double>();
Buy a beer for me, if it would be useful :)
I don't know if you're still interested, but I saw this one and I liked the challenge. If you use .Net 4 (having the Enumberable.Zip method) there is a very concise way to do this (given the conditions under futher info):
arrayA.Zip(arrayB, (a,b) => new {a,b})
.Where(x => x.a > lower && x.a < upper)
.Select (x => x.b)
You may want to use >= and <= to make the range comparisons inclusive.