Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I have a list of strings like this:
123.45 ABC
678.90 DEF
543.21 FED
I want to sort the list alphabetically using the last 3 characters of each list element.
EDIT: Using C#, how do I alphabetize this list by using the last 3 characters of each element?
What I would first do is to ensure that I filter out all strings that have less than 3 characters. Then I would order them as:
var items = new List<string> { "13 zzz", "12 yyy", "11 zzz" };
items = items.Where(i => i.Length > 2)
.OrderBy(i => i.Substring(i.Length - 3))
.ToList();
To order by the last three characters, you can just take the Substring starting at Length - 3 and use that in the OrderBy method (note that we should first check that item.Length > 2 so that Substring doesn't throw an execption):
var items = new List<string> {"543.21 FED", "123.45 ABC", "678.90 DEF"};
items = items
.OrderBy(item => item?.Length > 3 ? item.Substring(item.Length - 3) : item)
.ToList();
// result: {"123.45 ABC", "678.90 DEF", "543.21 FED"}
Alternatively, you can write a custom comparer for the strings and then pass that to the Sort method. We can include a constructor for our comparer that takes in an int that specifies how many characters we want to count from the end of the string to make it more flexible (like if you want to use the last 5 characters, or the last 2, etc.).
public class OrderByLastNChars : Comparer<string>
{
public int N { get; set; }
public OrderByLastNChars(int n)
{
N = n;
}
public override int Compare(string x, string y)
{
if (x == null) return y == null ? 0 : -1;
if (y == null) return 1;
var first = x.Length > N ? x.Substring(x.Length - N) : x;
var second = y.Length > N ? y.Substring(x.Length - N) : y;
return first.CompareTo(second);
}
}
Then this can be used like:
items.Sort(new OrderByLastNChars(3));
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I have two lists xList and yList. They are used for storing coordinates. I need to get user input and ascertain if the values given by user (x, y) are in the lists (x in xList and y in yList). If the x variable is in xList and y in yList I need to know if they are at the same index. I was thinking that I would get every index of variable specific for the list and then compare indexes form both lists to find out if the user input match coordinates in lists. If there is a match the output will be index where the match is. Otherwise, the output will be -1. Example: xList is filled with numbers 5,5,2,2 the yList with 4,3,2,1. User input is x=5 and y=1. We know that 5 is in xList on index 0 and 1. One is in yList at index 3. So we know, that the numbers are in the lists but not on the same indexes therefore the output is -1. Then the user give us input x=5 and y=3. We know, that in xList are indexes 0 and 1. In yList is index 1. So the match is the index 1 and the output is 1. The way to do it is probably LinQ. But C# and OOP overall isn't my cup of tea and I can't make heads or tails out of it. But I also need to finish this. Is there any good soul, that would help me?
You can have a list of Coordinates like:
public class Coordinate
{
public int X {get; set;}
public int Y {get; set;}
}
and your List as List<Coordinate>()
this way you can do it easily like:
bool exists = list.Any(l => l.X == x && x.Y == y);
However if you insist on having 2 separate lists, you can do it with a simple loop
int i = 0;
for(i=0;i<xList.Length;i++)
{
if(xList[i] == x && yList[i] == y) break;
}
if(i > xList.Length)
// not found
else
{
//i is the index
}
xList
.Select((x, ind) => (x, (int?)ind))
.FirstOrDefault(tuple => tuple.x == yList[tuple.ind])
.ind ?? -1
We select the xList items as tuples of items and indices.
We get the first in the list for which the corresponding item in the other list is equal, and return the index. Because the index is int? we can use ?? -1 to return -1 if it is not found.
If you would like all possible matches, do instead:
xList
.Select((x, ind) => (x, ind))
.Where(tuple => tuple.x == yList[tuple.ind])
.Select(tuple => tuple.ind)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
So I was attempting a challenge on Codewars and after completing it, I saw the following solution.
public static List<string> SinglePermutations(string s)
=> $"{s}".Length < 2
? new List<string> { s }
: SinglePermutations(s.Substring(1))
.SelectMany(x => Enumerable.Range(0, x.Length + 1)
.Select((_, i) => x.Substring(0, i) + s[0] + x.Substring(i)))
.Distinct()
.ToList();
Could anyone explain this to me? I have seen the ternary operator and recursion before. I am relatively new to Select and Select many. However, putting all these into one question has confused me. Thanks!
After simplifications I noted in my comments, here is some explanation:
public static List<string> SinglePermutations(string s)
=> s.Length == 1
? new List<string> { s } // a single character string only has one permuatation, itself
: SinglePermutations(s.Substring(1)) // get all the permutations of the "tail" of the string i.e. the string minus the first char
// for each tail permutation
.SelectMany(aTailPermutation =>
// loop over all the positions in the permutation from before the first char to after the last char
Enumerable.Range(0, aTailPermutation.Length + 1)
// for each position, put the original first char in that position
.Select(i => aTailPermutation.Substring(0, i) + s[0] + aTailPermutation.Substring(i))
) // flatten the resulting list of strings
.Distinct() // throw away any duplicates
.ToList(); // return as a list
It might be easier understood if converted to procedural code from LINQ:
public static List<string> SinglePermutationsFn(string s) {
if (s.Length == 1) // a single character string
return new List<string> { s }; // only has one permuatation, itself
else {
var ans = new List<string>();
// get all the permutations of the "tail" of the string i.e. the string minus the first char
var tailPermutations = SinglePermutations(s.Substring(1));
// loop over all the tail permutations
foreach (var aTailPermutation in tailPermutations) {
// loop over all the positions in the permutation from before the first char to after the last char
for (int permutationPos = 0; permutationPos < aTailPermutation.Length + 1; ++permutationPos) {
// for each position, put the original first char in that position
ans.Add(aTailPermutation.Substring(0, permutationPos) + s[0] + aTailPermutation.Substring(permutationPos));
}
}
return ans.Distinct() // throw away any duplicates
.ToList(); // return as a list
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
below is the Method I am trying to solve.....
public int IndexOfLastUniqueLetter(string str)
I have not tried any code yet because I have no Idea how to solve it.
Please advise how to solve this method and the code which to do so. Please and thank you.
The algorithm boils down to these two steps:
Find which letters are unique,
Find the last of these unique letters in the original string.
Counting occurrences of each letter could be done with a loop, or with an associative container, depending on your preferences. If count is 1, the letter is unique; otherwise, it is not unique. Finding last-of could be done by walking the string backward.
The only thing to worry about here is what to do when there are no unique letters in the string (e.g. "aaaa" or "abab"). Your code should detect this condition explicitly, and return -1.
If i may suggest a single line of code,
Get a list of all unique letters
Iterate through backwards to see which one occurs only once in the string.
Return the index of that letter (-1 if it doesnt exist)
public static int IndexOfLastUniqueLetter(string original)
{
return original.IndexOf(
original.Distinct()
.Reverse()
.Where(x => original.Where(y => y.Equals(x)).Count() == 1)
.FirstOrDefault());
}
Easiest method is to parse twice the string.
I personally used a Dictionary<char, int> which is storing the occurrence for any character in my string.
Once parsed, and because Dictionary does not preserve order, you can (as dasblinkenlight) mentioned parse your string backward.
Below is my method:
int GetIndexOfLastUniqueOccurrence(string msg)
{
var occurrenceChar = new Dictionary<char, int>();
// Parse the string to count occurrence
for (int i = 0; i < msg.Length; i++)
{
if (occurrenceChar.ContainsKey(msg[i]))
occurrenceChar[msg[i]]++;
else
occurrenceChar.Add(msg[i], 1);
}
// Parse backward the string to find the last one with occurrence == 1
for (int i = msg.Length - 1; i >= 0; i--)
{
var occurrence = occurrenceChar[msg[i]];
if (occurrence == 1)
return i;
}
return -1; // If string does not contain any unique char
}
Below are some tests:
Console.WriteLine(GetIndexOfLastUniqueOccurrence("abcddeeff")); // 2
Console.WriteLine(GetIndexOfLastUniqueOccurrence("aaaaaabbbbbcccc")); // -1
Console.WriteLine(GetIndexOfLastUniqueOccurrence("abcdefgg")); // 5
Something less verbose
If you want to create your dict out of the string using LINQ:
var occurrenceChar = msg.GroupBy(c => c).Select(c => new { Char = c.Key, Count = c.Count() }).ToDictionary(x => x.Char, x => x.Count);
Something even less verbose (inspired by #Jawad anwser):
return message.IndexOf(
message
.Distinct()
.Reverse()
.FirstOrDefault(x => message.Count(y => y.Equals(x)) == 1));
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have a list of Teams. A team is defined in this way:
public class Team
{
public int ID { get; set; }
public string Name { get; set; }
}
After I query the database with db.Teams.ToList(), which returns a List<Team>, I need to push one of the teams of that list with the name "Total" to the end of the list. How can I achieve this?
First, you can do that directly in the query:
var list = db.Teams.OrderBy(t => t.Name == "Total" ? 1 : 0).ToList();
But if you insist doing it after the list is populated, then you can use the FindIndex method to find the index of the total item (if any) and them move the item to the end using RemoveAt and Add methods:
var list = db.Teams.ToList();
int index = list.FindIndex(t => t.Name == "Total");
if (index >= 0 && index != list.Count - 1)
{
var total = list[index];
list.RemoveAt(index);
list.Add(total);
}
In the later case, if you don't really care about the order of the other items in the list, another more efficient way would be to simply exchange the total with the last element:
if (index >= 0 && index != list.Count - 1)
{
var total = list[index];
list[index] = list[list.Count - 1];
list[list.Count - 1] = total;
}
Get the list and move the one you want to the last index. Note that you don't need to order the list. Say your object is 2 in this case:
List<int> list = new List<int>
{
0,
1,
2,
3,
4
};
// get the object o(n)
int tmp = list.IndexOf(2);
// remove it
list.RemoveAt(2);
// add it to the end of list
list.Add(tmp);
Short answer: Generate hash-code
Please look at this answer from #Jon Skeet - https://stackoverflow.com/a/8094931/6830901
More simple based on the requirement as I understand:
Do a lookup on Team.Name != "Total" in your first loop
and after the looping is over, check in the list for Team.Name == "Total"
It doesn't matter where the Team is placed (think about a shared list). It is up to how we use the query than to where we inject the object
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
What is wrong here? How to filter out negative elements correctly?
class Program
{
static void Main(string[] args)
{
int[] array = { 1, 2, -3, 4, 5, -1, 4, -2 };
double sumOfElem = array.Sum(element => element < 0);
Console.WriteLine(sumOfElem);
}
}
I think you need this:
double sumOfElem = array.Sum(element => (element < 0 ? 0 : element));
This way you are using an overload of Sum that utilises a transform function (so called selector), that is applied to each element of the array.
The above filters out negative elements. If you want to filter out positive ones, then simply inverse the comparison operator:
double sumOfElem = array.Sum(element => (element > 0 ? 0 : element));
You could try this one:
int sumOfElem = array.Where(element => element < 0)
.Sum();
You can't filter your values inside the Sum. You should first filter the values and then sum them.
Update
Saying that You can't filter your values inside the Sum, I mean you can't pass a predicate in the Sum method.