Combine multiple values into one in c# - c#

I have a dictionary having ids as key and value will be the ids to which it will be clubbed ( which is actually the ref data).
There is one more list which only contains the ids but for specific name.
First list have 100 different ids from 1 to 100.
I am checking whether the ids for specific name in list 2 is present in list 1.If they are present then saving those ids. But there is a special condition in it.
e.g. If ids present in list 2 have clubbed ids (which we are checking from the ref dictionary) then we have to save only the clubbed id
Let us suppose the ids in list 2 is 1,10,21. 1 and 10 are clubbed with 21.Therefore, I only have to save one id which is the clubbed one i.e. 21 but not to save 1 and 10. In this case we are saving only 1 instead of 3.
If these ids dont have any clubbed id then 3 ids will be saved (1,10,21).
Updated:
Dictionary have 1 to 100 ids and some of the ids have clubbed ids and some dont
Dictionary<int,string> dict = new Dictionary<int,string>();
//Key is id and the value is clubbedid
dict.Add(1,"21");
dict.Add(10,"21");
dict.Add(21,"None");
// etc
//In the list 2 we have ids for specific name
List<int> list2 = new List<int>();
list2.Add(1);
list2.Add(10);
list2.Add(21);
First i will check whether all the three ids in list 2 are in reference dictionary.And then will assign the value in other list of object in the field Id.
foreach(int value on list2)
{
if(dict.ContainsKey(value))
{
List<class> list3 = new List<class> list3();
list3.Id = value;
}
}
So I have added all the three ids 1,10,21 one by one in id field of list3. Now the list3 contains three ids. In the simple case it is correct where none of the id have clubbed id.
But as you can see in my reference dictionary, ids 1 and 10 have clubbed id as 21.Therefore, in the list3 I have to store only one value which is 21 (only clubbed id removing the other one 1 and 10)
Any help.

Your question is not particularly clear - as per the comments currently.
To have a stab at this - assuming list1 is an IEnumerable<int> and list2 is a Dictionary<int,int[]> then I think what you're trying to do is along the lines of the following
// numbers 1-100
var list1 = Enumerable.Range(1,100).ToList();
// 3 entries
var list2 = new Dictionary<int,int[]>(){
{1,new[]{21}},
{10,new[]{21}},
{21,new int[0]}
};
var result = list2.SelectMany(item => {
if(!list1.Contains(item.Key))
return Enumerable.Empty<int>();
if(item.Value != null && item.Value.Length>0)
return item.Value;
return new[]{item.Key};
}).Distinct();
Live example: http://rextester.com/RZMEHU88506
Having updated your question, this might work for you:
var list3 = list2.Select(x => {
int value = 0;
// if the dict contains the key and the value is an integer
if(dict.ContainsKey(x) && int.TryParse(dict[x], out value))
return value;
return x;
})
.Distinct()
.Select(x => new MyClass(){ Value = x })
.ToList();
Live example: http://rextester.com/KEEY8337

Related

How to sort an array depending on the other array [duplicate]

This question already has answers here:
List<string> complex sorting
(5 answers)
Closed 2 years ago.
Hi i have 2 arrays and both have same values but in different order, i want to sort 1 array depending on the other can you help me on how to do this.
Code :
1 array is say string[] abc = []; and other array that is items which is shown below in the code. As i said both have same number of values
return new PdfGenerationRequest
{
Email = userEmail,
FileName = zipName,
AppName = appName,
Period = period,
Year = year,
Quarter = quarter,
TemplateTypeId = templateTypeId,
WPGroup = wpGroup,
MyDealsOnly = myDealsOnly,
Watermark = watermark,
Items = items.OrderBy(x => x.FileName).ToArray()
};
Currently i am sorting in asc order based on items array.
Please suggest me on how to sort the items array based on the abc array.
so for ex :
Abc has 3 elements that is Apple, Cat, Bat
and items has 3 elements that is cat, bat, apple
but here i want to sort it based on ABC the items array should be ordered. So here the end result from items should be Apple, Cat, Bat
The wording of the question is slightly confusing, and it's not completely clear if you're looking for a case-insensitive comparison or not, but going off of this statement:
"abc has 3 elements: {"Apple", "Cat", "Bat"} and items has 3 elements that is {"cat", "bat", "apple"} [and] I want to sort it based on abc
The way to compare one to another is to use the index of the item in the first array for sorting the second array, which we can do by using the Array.IndexOf method. For example:
var abc = new [] {"Apple", "Cat", "Bat"};
var items = new[] {"Cat", "Bat", "Apple"};
items = items
.OrderBy(item =>
abc.Contains(item) ? Array.IndexOf(abc, item) : int.MaxValue)
.ToArray();
// Now items = {"Apple", "Cat", "Bat"}
Note that we're using the ternary operator ?: to return int.MaxValue if Contains returns false, which will put any items that aren't in abc at the end of the sort order.
But in your example you showed that items actually contained lower-case versions of the strings in abc. If this is the case and you want to match them with a case-insensitive comparison, one way to get the index is to use the System.Linq extention method Select to get both the item and it's index from abc, then find the FirstOrDefault item that matches the current item in items using a case-insensitive comparison:
var abc = new [] {"Apple", "Cat", "Bat"};
var items = new[] {"cat", "bat", "apple"};
items = items.OrderBy(i => abc.Select((item, index) => new {item, index})
.FirstOrDefault(a =>
i.Equals(a.item, StringComparison.OrdinalIgnoreCase))?.index ?? int.MaxValue)
.ToArray();
// Now items = {"apple", "cat", "bat"}
Note that because FirstOrDefault will return null if the item doesn't exist, we're using the ?. and ?? operators to once again return int.MaxValue if that happens to put any items that aren't in abc at the end of the sort order.

How can I convert this linq to bool

How to convert a query to bool?
I used the "ALL (x => x)" but did not give the answer I needed.
Code Line
checkItemInventory.Where(x => listCost.Contains(x.Id));
In this case, the listcost would have 2 items, I needed to check if the checkItemInventory has these 2 items.
"All items in the inventory have an id that present in listcost". listCost needs to have the same number of items as inventory (assuming Id is unique) possibly more, to stand a chance of returning true
checkItemInventory.All(x => listCost.Contains(x.Id))
"At least one item in the inventory has an id that is also in listCost". Listcost could minimally have only one id in it, to stand a chance of returning true
checkItemInventory.Any(x => listCost.Contains(x.Id))
As you can see, neither of these are what you want as you seem to be saying you want to check whether every item in listcost is also present in the inventory. This is like the top code, but the other way round ("all items in listCost are present in inventory" vs "all items in inventory are present in listcost"
I think I'd make a dictionary out of the inventory first, unless it's already something that supports a fast lookup:
var d = checkItemInventory.Select(x => new { x.Id, x.Id }).ToDictionary();
var boolResult = listCost.All(lc => d.ContainsKey(lc));
If inventory is small, you could use this approach:
listCost.All(lc => checkItemInventory.Any(cii => cii.Id == lc));
Just be mindful that internally it might do something like:
bool all = true;
foreach(lc in listCost){
bool found = false;
foreach(cci in checkItemInventory)
if(lc == cci.Id){
found = true;
break;
}
all &= found;
if(!all)
return false;
}
return true;
Which is a lot of repeated comparisons (for every item in listCost, the whole inventory is scanned), could be slow
Edit
I asked for clarification of how you store your inventory and your costs of building items. Here's one assumption I made, and how a solutio based on it might work:
Assuming your inventory has the kind of item and a count saying how many of that item the player is carrying:
class InventoryItem{
int ItemKindId { get; set;}
int CountOf { get; set; }
}
player.Inventory.Add(new InventoryItem() {
ItemKindId = Constants.WOOD, //1
CountOf = 10 //holding 10 items of wood
};
player.Inventory.Add(new InventoryItem() {
ItemKindId = Constants.STONE, //2
CountOf = 5 //holding 5 items of stone
};
Assuming you have a Recipe for making e.g. an axe, it needs 1 wood and 2 stone, but it lists them in simple order:
int[] axeRecipe = new int[] { Constants.WOOD, Constants.STONE, Constants.STONE };
Might be easiest to group the recipe:
var recipe = axeRecipe.GroupBy(item => item)
/*
now we have a grouping of the recipe[item].Key as the material and a
recipe[item].Count() of how much. The group is like a dictionary:
recipe[Constants.WOOD] = new List<int>{ Constants.WOOD };
recipe[Constants.STONE] = new List<int>{ Constants.STONE, Constants.STONE, };
A group item has a Key and a list of objects that have that key
Because my recipe was simply ints, the Key is the same number as all the
items in the list
*/
//for all items in the recipe
grp.All(groupItem =>
//does the player inventory contain any item
playerInventory.Any(inventoryItem =>
//where the material kind is the same as the recipe key (material)
inventoryItem.ItemKindId == groupItem.Key &&
//and the count they have of it, is enough to make the recipe
inventoryItem.CountOf >= groupItem.Count()
);
You can of course reduce this to a single line if you want: axeRecipe.GroupBy(...).All(...)
You could map the listCost to a list of int and then use Except() and Any() to check whether all items are contained:
bool containsAll = !listCost.Select(x => x.Id).Except(checkItemInventory).Any();
[UPDATE]
You are telling us the following:
How to convert a query to bool? I used the "ALL (x => x)" but did not give the answer I needed.
checkItemInventory.Where(x => listCost.Contains(x.Id));
In this case, the listcost would have 2 items, I needed to check if
the checkItemInventory has these 2 items.
if you need to check if there is any result then you can use:
bool hasItems = checkItemInventory.Where(x => listCost.Contains(x.Id)).Any();
if you need to count the result you can use
checkItemInventory.Where(x => listCost.Contains(x.Id)).Count();
You could use a Join to create a method based Linq query and use the results to check if the length of the list is greater than 0. Then turn that into a boolean.
var query = checkItemInventory.Join(listCost,
inventory => inventory.Id,
cost => cost.Id,
(inventory, cost) => new { id = inventory.Id });
var count = query.ToList().Count();
var b = (count > 0);
If I get it correctly, listCost can have less elements than checkItemInventory. You want to check that all elements in listCost have a corresponding element in checkItemInventory. Correct? If yes, try this:
listCost.All(x => checkItemInventory.Contains(x));
I don't know the type of these lists, so you might need to use x.id in some places

Sorting lists in c#

I have two lists in C#.
public List<MyClass> objectList = new List<MyClass>(); // it is filled with MyClass objects
public List<int> numberList = new List<int>(); // it is filled with numbers
The index of numbers in the numberList correspond to object index in the objectList: For example: objectList[0] = o1 and numberList[0] = 3 ;
objectList[1] = o2 and numberList[1] = 5 ...
objectList: |o1 | o2 | o3 | o4 | o5 | ...
numberList: 3 5 6 1 4 ...
I want to sort the numbers in the numberList in ascending order and I want for the objetcs in objectList to move with them:
After sorting:
objectList: |o4 | o1 | o5 | o2 | o3 | ...
numberList: 1 3 4 5 6 ...
In practical use I need this for implementing the Hill climbing algorithm on a N queen problem. In the objectList I store positions of all the queens on the board and in the numberList I store the calculated heuristics for the positions. Then I want to sort the numberList so I get the position with the lowest heuristic value. The goal is to move to the position with the lowest heuristic value.
Transform your object list into a sequence of items paired with their indices:
var pairs = objectList.Select(item, index) => new { item, index };
Now you have something you can use to do an ordering:
var orderedPairs = pairs.OrderBy(pair => numberList[pair.index]);
Now you have an ordered list of pairs. Turn that back into an ordered list of items:
var ordered = orderedPairs.Select(pair => pair.item);
and turn it into a list:
var orderedList = ordered.ToList();
Note that your original lists are not altered. This creates a new list that is in the order you want.
Of course you can do it all in one expression if you like:
objectList = objectList
.Select((item, index) => new { item, index } )
.OrderBy(pair => numberList[pair.index])
.Select(pair => pair.item)
.ToList();
Now, all that said: it sounds like you're doing too much work here because you've chosen the wrong data structure. It sounds to me like your problem needs a min heap implementation of a priority queue, not a pair of lists. Is there some reason why you're not using a priority queue?

How to select all objects that have a property value in list of values?

I have a table named Items. Items have a property named "locationId" Given a list of location Ids, how do I select all items?
List example
List<long> locationIds = new List<long> { 1, 2, 3 };
Essentially the query below, but for multiple locations at once:
var sleectedItems= db.Items.Select(i => i.LocationId == 2);
You need to use Where with Contains:
var selectedItems = db.Items.Where(x => locationIds.Contains(x.LocationId));

Using a nested foreach to store one foreach value into an array

Alright so I didn't really know how to word this question, but I did my best. The goal I am trying to accomplish is to go through categories using a foreach loop. Inside the category foreach loop another foreach loop will go through Numbers. Right now it is grabbing ever value in the tables and storing them into an array. My goal is to only store the highest number in each category into the array.
Here is how the tables would look:
Category Table
Title NumberId
Type 1
Priority 2
Likelihood 3
Numbers Table
Order NumberId
3 1
2 1
1 1
3 2
2 2
1 2
3 3
2 3
1 3
So my goal would be instead of storing every order value into the array. I would like to store the highest number according to each number id. So there array would include 3,3,3.
This is what I have that stores every number into an array:
int[] values = new int[count];
foreach(var x in Category)
{
foreach(var w in x.Numbers)
{
values[y] = w.Order;
y++;
}
}
Solution:
int[] values = new int[count];
foreach(var x in Category)
{
foreach(var w in x.Numbers)
{
values[y] = x.Numbers.Select(o => o.Order).Max();
y++;
break;
}
}
You can use IEnumerable.Max() :
foreach(var x in Category)
{
values[y] = x.Numbers.Select(o => o.Order).Max();
y++;
}
This can be accomplished relatively easily through LINQ as:
int[] values = new int[count];
foreach(var x in Category)
{
values.[y] = x.Numbers.OrderBy(w => w.Order).Reverse().First();
y++;
}
This orders the x.Numbers by their ascending order, reverses the order (to place the highest value first in the order), and then selects the first value.
Ensure with this method that you've actually got a value for x.Number, else you'll get an exception thrown by the .First() call.
If you're unable to use LINQ (e.g. if you're on .NET 2.0), then consider using a Dictionary with the Category as the key, and the highest Number as the value:
Dictionary<int, int> categoriesByHighestOrders = new Dictionary<int, int>();
foreach(var x in Category)
{
if (!categoriesByHighestOrders.Keys.Contains[x.SomeIndetifier])
categoriesByHighestOrders.Add(x.SomeIdentifier, 0);
foreach(var w in x.Numbers)
{
if (categoriesByHighestOrders[x.SomeIndetifier] < w.Order
categoriesByHighestOrders[x.SomeIndetifier] = w.Order;
}
}

Categories