ReIndex Number List but keep Duplicates in Order C# - c#

I'm trying to reorder a list that essentially gets rid of duplicates. Which I have been able to do. The part that is tripping me up is, if there are duplicates I want to keep them, and maintain the order
Examples -
Input = 1,3,3,4
Output = 1,2,2,3
Input = 1,3,5,6,6
Output = 1,2,3,4,4
Any help would be appreciated.
EDIT -
Code I've attempted.
for (int i = 1; i <= numList.Count; i++)
{
if (numList[i - 1] == numList[i])
{
foreach (var item in numList.Where(x => x == numList[i - 1]))
{
testList.Add(item);
i++;
}
foreach (var item in testList)
{
numList.Add(item);
}
}
else
{
numList[i - 1] = i;
}
}

Your question has nothing to with sorting... but I think I understood what you are looking for, and the following code should provide it:
List<Int32> numbers = new List<Int32> { 1, 3, 3, 4 };
List<Int32> result = new List<Int32>(numbers.Count);
Int32 currentValue = 1;
Int32 lastNumber = numbers[0];
for (Int32 i = 0; i < numbers.Count; ++i)
{
Int32 number = numbers[i];
if (numbers[i] != lastNumber)
++currentValue;
result.Add(currentValue);
lastNumber = number;
}
foreach (Int32 number in result)
Console.WriteLine(number); // Output: 1, 2, 2, 3
Please, visit this link to try a working demo, which implements the following function:
private static List<Int32> IndexNumbers(List<Int32> input)
{
List<Int32> numbers = input.OrderBy(x => x).ToList();
List<Int32> result = new List<Int32>(input.Count);
Int32 currentValue = 1;
Int32 lastNumber = numbers[0];
for (Int32 i = 0; i < numbers.Count; ++i)
{
Int32 number = numbers[i];
if (numbers[i] != lastNumber)
++currentValue;
result.Add(currentValue);
lastNumber = number;
}
return result;
}

Something like this? Note that it is unclear whether we expect the input to be out of order or not. If we're allowed to change the input array, a simple Array.Sort(values) at the top of Rebase would ensure that aspect.
static void Main(string[] args)
{
Console.WriteLine(string.Join(", ", Rebase(1, 3, 3, 4))); // 1, 2, 2, 3
Console.WriteLine(string.Join(", ", Rebase(1, 3, 5, 6, 6))); // 1, 2, 3, 4, 4
}
static int[] Rebase(params int[] values)
{
// Array.Sort(values); // if not already sorted, and allowed to mutate
int prev = values[0];
var result = new int[values.Length];
int val = result[0] = 1;
for (int i = 1; i < values.Length; i++)
{
var current = values[i];
if (current != prev)
{
val++;
prev = current;
}
result[i] = val;
}
return result;
}
Note that you could also choose to overwrite the input array rather than create a new array to return.

Try this using LINQ:
var reindexed = numList
.OrderBy(n => n)
.GroupBy(n => n)
.SelectMany((g, i) => g
.Select(e => i + 1));

First off, figure out what the old number should match to. Distinct and OrderBy are probably you're friends here
List<int> input = new List<int> { 1, 3, 3, 4 };
var dictionary = new Dictionary<int, int>();
var index = 1;
foreach (var n in input.Distinct().OrderBy(n => n)) {
dictionary.Add(n, index++);
}
var output = input.Select(n => dictionary[n]);

Related

return array with elements that can be repeated only N times

I am trying to practice some c# questions and I came across a question where given an integer of array, return the array with elements that can be repeated only N times. So, if I have {1,2,3,4,1,1,2,3} and my N=2, my result should be {1,2,3,4,1,2,3}. I tried something but I get the result as {2,3,4,1,1,2,3}.I don't want the first repeated element be removed.
This is what I have tried :
int[] intArray = {3,2,3,1,3};
int N = 2;
var list = new List<int>(intArray);
var newList = new List<int>();
for (int i = 0; i < list.Count; i++)
{
int occur = 1;
for (int j = i+1; j < list.Count; j++)
{
if (occur < N && list[i] == list[j])
{
occur++;
newList.Add(list[j]);
}
else
{
if (list[i] == list[j] )
list.Remove(list[j]);
}
}
}
foreach (var l in list)
{
Console.WriteLine(l);
}
}
}
I would really appreciate any help or guidance.
I suggest using Dictionary<T, int> to count appearances:
private static IEnumerable<T> RepeatOnly<T>(IEnumerable<T> source, int times) {
Dictionary<T, int> counts = new Dictionary<T, int>();
foreach (var item in source) {
int count;
if (counts.TryGetValue(item, out count))
counts[item] = ++count;
else
counts.Add(item, count = 1);
if (count <= times)
yield return item;
}
}
....
int[] source = new int[] { 1, 2, 3, 4, 1, 1, 2, 3 };
int[] result = RepeatOnly(source, 2).ToArray();
Console.Write(string.Join(Environment.NewLine, result));
I'd use a dictionary to keep track of how many times each integer has been encountered:
int[] intArray = { 1, 2, 3, 4, 1, 1, 2, 3 };
int N = 2;
var lookup = new Dictionary<int, int>();
LIst<int> list = new List<int>();
foreach (int num in intArray)
{
if (!lookup.ContainsKey(num))
{
lookup[num] = 1;
list.Add(num);
}
else if (lookup[num]++ < N)
{
list.Add(num);
}
}

How to get Max value same length array in c#

My array is below
int[] T1 = new int[]{1,5,4};
int[] T2 = new int[]{2,4,3};
int[] T3 = new int[]{7,9,1};
A result of the sequence I want it is as follows .
int[] result = {7,9,4}
I want to look for a max value same index[(e.g) 1,2,7) in array.
and Merging array is int[] result = {7,9,4}
please let me know best way
thanks
Here is a simple method for performing your desired operation.
int[] result = new int[T1.Length];
for (int i = 0; i < T1.Length; i++)
{
result[i] = new[] {T1[i], T2[i], T3[i]}.Max();
}
You'll have to add using System.Linq in order to enable the Max() extension.
EDIT
Here is a method that allows you to use any number of arrays:
static T[] MaxElements<T>(params T[][] arrays) where T : IComparable<T>
{
return Enumerable.Range(0, arrays[0].Length)
.Select(i => Enumerable.Range(0, arrays.Length)
.Select(a => arrays[a][i]).Max()).ToArray();
}
You'll have to add the using System.Linq; for this one too. You'll have to make sure that all the elements passed in have the same lengths else you will run into an IndexOutOfRangeException.
It can be used as follows;
var result = MaxElements(T1, T2, T3);
Here is what you need:
static void Main(string[] args)
{
GetMaxArray(new[] { 1, 5, 4 }, new[] { 2, 4, 3 }, new[] { 7, 9, 1 });
}
private static void GetMaxArray(params int[][] m)
{
var length = m.First().Length;
var r = new int[length];
for (var i = 0; i < length; i++)
r[i] = m.Select(a => a[i]).Max();
}
public int[] GetMaxValueArray(List<int[]> arrayList)
{
int[] result = null;
int maxArraySize;
int maxCurrentArrayItemValue;
if (arrayList != null && arrayList.Count > 0)
{
maxArraySize = 0;
foreach (int[] array in arrayList)
if (array.Length > maxArraySize)
maxArraySize = array.Length;
result = new int[maxArraySize];
for (int i = 0; i < maxArraySize; i++)
{
maxCurrentArrayItemValue = 0;
foreach (int[] array in arrayList)
if (i < array.Length)
if (array[i] > maxCurrentArrayItemValue)
maxCurrentArrayItemValue = array[i];
result[i] = maxCurrentArrayItemValue;
}
}
return result;
}

Adding all possible sum, from a list of values to that same list of values in a list

I have a List containing values 10, 20, 30, 50,30
i would like to add all possible sum of the values present in the list that is:
10+20 = 30
10+30 = 40
10+50 = 60
20+30 = 50
10+20+30+50+30
the list i declared is something like this:
List list = new List();
and values(i.e 10, 20, 30, 50, 30) were added using a for loop.
Done so far:
List<int> list = new List<int>();
list.Add(3);
list.Add(7);
list.Add(8);
list.Add(1);
var length = list.Count();
for (int i = 0; i < length; i++)
{
var sum = 0;
sum = sum + list[i];
for (int j = i + 1; j < length; j++)
{
sum = sum + list[j];
list.Add(list[i] + list[j]);
}
list.Add(sum);
}
This works for me:
Func<IEnumerable<int>, IEnumerable<int>> getAllSelectionSums = null;
getAllSelectionSums = xs =>
{
if (!xs.Any())
{
return new [] { 0 };
}
else
{
return
from h in xs.Take(1).Concat(new [] { 0 })
from t in getAllSelectionSums(xs.Skip(1))
select h + t;
}
};
So, given var source = new [] { 3, 7, 8, 1 }; as the input I get the following result:
This is typically done with two for loops if you want only 2 elements. However, if you wanted to pick all combinations from 1 to all elements, you are looking for the power set.
I will answer it for just picking 2
List<int> sums = new List<int>();
for(int first = list.Length - 1; first >= 1; first--)
{
for(int second = first - 1; second >= 0; second--)
{
sums.Add(list[first] + list[second]);
}
}
You should also bracket this to make sure your list has at least 2 items in it...
Edit:
Since you've updated your question to show your implementation, I'll include code to generate power sets
public IEnumerable<IEnumerable<int>> PowerSet(IEnumerable<int> initialSet)
{
foreach (IEnumerable<int> set in PowerSetRecursive(initialSet, initialSet.Count() - 1))
{
yield return set;
}
}
private IEnumerable<IEnumerable<int>> PowerSetRecursive(IEnumerable<int> initialSet, int index)
{
if (index == 0)
{
yield return new int[] { };
yield return new int[] { initialSet.ElementAt(index) };
}
else
{
foreach (IEnumerable<int> set in PowerSetRecursive(initialSet, index - 1))
{
yield return new HashSet<int>(set);
yield return new HashSet<int>(set) { initialSet.ElementAt(index) };
}
}
}
You would then loop like this
foreach (IEnumerable<int> set in PowerSet(new int[] { 1, 2, 3, 4 }))
{
Console.WriteLine(set.Sum());
}

Longest subsequence in array

I am trying to solve my task using a List and I know I am very close to solving it but I am stuck now. Something is not ok in the code and I can not figure out what it is. Could you please take a look and help:
/*
Write a program that reads an array of integers and removes from it a minimal number of elements in such way that the
remaining array is sorted in increasing order. Print the remaining sorted array.
Example: {6, 1, 4, 3, 0, 3, 6, 4, 5}  {1, 3, 3, 4, 5}
*/
using System;
using System.Collections.Generic;
class RemoveMinimalElements
{
static void Main()
{
int n;
n = int.Parse(Console.ReadLine());
List<int> arr = new List<int>();
List<int> sorted = new List<int>();
int maxSubsetLenght = 0;
for (int i = 0; i < n; i++)
{
arr.Add(int.Parse(Console.ReadLine()));
}
for (int i = 1; i <= (int)Math.Pow(2, n) - 1; i++)
{
int tempSubsetLenght = 0;
string tempString = "";
List<int> temp = new List<int>();
for (int j = 1; j <= n; j++)
{
int andMask = i & (1 << j);
int bit = andMask >> j;
if (bit == 1)
{
temp.Add(arr[n - 1 - j]);
tempSubsetLenght++;
}
if (tempSubsetLenght > maxSubsetLenght)
{
maxSubsetLenght = tempSubsetLenght;
for(int k =1; k < temp.Count; k ++)
{
if (temp[k] >= temp[k - 1])
{
sorted = temp;
}
}
}
}
}
for (int i = sorted.Count - 1; i > 0; i--)
{
Console.WriteLine(sorted[i]);
}
}
}
I didn't follow the code, I just tested your app.
This is my first input: 5.
Then I entered these 5 inputs 2,4,6,8,10 so
arr = {2,4,6,8,10};
And when it came to the last lines it gave me the ArguementOutOfRangeException (Index was out of range. Must be non-negative and less than the size of the collection.) because it was trying to fetch arr[item] and item is 6 so it's trying to fetch arr[6] which does not exist.
I don't know if an exhaustive search is suitable for your case, but will this work for you?
static void Main(string[] args)
{
int[] input = new[] { 6, 1, 4, 3, 0, 3, 6, 4, 5 };
int[] expectedOutput = new[] { 1, 3, 3, 4, 5 };
int[] solution = TryGetSolution(input);
Console.WriteLine("Input: " + FormatNumbers(input));
Console.WriteLine("Expected Output: " + FormatNumbers(expectedOutput));
Console.WriteLine("Output: " + FormatNumbers(solution));
Console.ReadLine();
}
private static string FormatNumbers(int[] numbers)
{
return string.Join(", ", numbers);
}
private static int[] TryGetSolution(int[] input)
{
return TryWithoutAnyItem(input);
}
private static int[] TryWithoutAnyItem(int[] items)
{
return Enumerable.Range(0, items.Length)
.Select(i => TryWithoutItem(items, i))
.Where(solution => solution != null)
.OrderByDescending(solution => solution.Length)
.FirstOrDefault();
}
private static int[] TryWithoutItem(int[] items, int withoutIndex)
{
if (IsSorted(items)) return items;
var removed = items.Take(withoutIndex).Concat(items.Skip(withoutIndex + 1));
return TryWithoutAnyItem(removed.ToArray());
}
private static bool IsSorted(IEnumerable<int> items)
{
return items.Zip(items.Skip(1), (a, b) => a.CompareTo(b)).All(c => c <= 0);
}
}
I solved it! Thank you very much for your support. I am a beginer and I am not able to use and understand more difficult stuff yet so here is what I did whit the things I already know:
/*
Write a program that reads an array of integers and removes from it a minimal number of elements in such way that the
remaining array is sorted in increasing order. Print the remaining sorted array.
Example: {6, 1, 4, 3, 0, 3, 6, 4, 5}  {1, 3, 3, 4, 5}
*/
using System;
using System.Collections.Generic;
class RemoveMinimalElements
{
static bool CheckAscending(List<int> list)
{
bool ascending = true;
for (int i = 0; i < list.Count - 1; i++)
{
if (list[i] > list[i + 1])
{
ascending = false;
}
}
return ascending;
}
static void Main()
{
int n;
n = int.Parse(Console.ReadLine());
List<int> arr = new List<int>();
List<int> sorted = new List<int>();
int maxSubsetLenght = 0;
for (int i = 0; i < n; i++)
{
arr.Add(int.Parse(Console.ReadLine()));
}
for (int i = 1; i <= (int)Math.Pow(2, n) - 1; i++)
{
int tempSubsetLenght = 0;
List<int> temp = new List<int>();
for (int j = 1; j <= n; j++)
{
if (((i >> (j - 1)) & 1) == 1)
{
temp.Add(arr[j - 1]);
tempSubsetLenght++;
}
}
if ((tempSubsetLenght > maxSubsetLenght) && (CheckAscending(temp)))
{
sorted = temp;
maxSubsetLenght = tempSubsetLenght;
}
}
for (int i = 0; i < sorted.Count; i++)
{
Console.WriteLine(sorted[i]);
}
}
}
This works for me
private static void FindLongestRisingSequence(int[] inputArray)
{
int[] array = inputArray;
List<int> list = new List<int>();
List<int> longestList = new List<int>();
int highestCount = 1;
for (int i = 0; i < array.Length; i++)
{
list.Add(array[i]);
for (int j = i+1; j < array.Length; j++)
{
if (array[i] < array[j])
{
list.Add(array[j]);
i++;
}
else
{
break;
}
i = j;
}
// Compare with in previous lists
if (highestCount < list.Count)
{
highestCount = list.Count;
longestList = new List<int>(list);
}
list.Clear();
}
Console.WriteLine();
// Print list
Console.WriteLine("The longest subsequence");
foreach (int iterator in longestList)
{
Console.Write(iterator + " ");
}
Console.WriteLine();
}

The Most frequent Number in an array

I have this Array i wrote a function MostFreq that takes an array of integers and return 2 values : the more frequent number in the array and its frequency check this code i worte what do you think ? is there a better way to do it?
static void Main()
{
int [] M={4,5,6,4,4,3,5,3};
int x;
int f=MyMath.MostFreq(M,out x );
console.WriteLine("the most Frequent Item = {0} with frequency = {1}",x,f);
}
=====
in the class Mymath
public static int MostFreq(int[] _M, out int x)
{
//First I need to sort the array in ascending order
int Max_Freq, No_Freq, i, k;
Array.Sort(_M);
k = _M[0];
Max_Freq = 0; i = 0; x = 0;
while (i < _M.Length)
{
//No_Freq= the frequency of the current number
No_Freq = 0;
//X here is the number which is appear in the array Frequently
while (k == _M[i])
{
No_Freq++;
i++;
if (i == _M.Length)
break;
}
if (No_Freq > Max_Freq)
{
//so it will be printed the same
Max_Freq = No_Freq;
x = k;
}
if (i < _M.Length) k = _M[i];
}
return (Max_Freq);
}
LINQ it up. I know this is in VB but you should be able to convert it to C#:
Dim i = From Numbers In ints _
Group Numbers By Numbers Into Group _
Aggregate feq In Group Into Count() _
Select New With {.Number = Numbers, .Count = Count}
EDIT: Now in C# too:
var i = from numbers in M
group numbers by numbers into grouped
select new { Number = grouped.Key, Freq = grouped.Count()};
Assuming you can't use LINQ, I'd probably approach the algorithm like this:
Create Key/Value dictionary
Iterate your array, add a key the dictionary for each unique elem, increment the value each time that element is repeated.
Walk the dictionary keys, and return the elem with the highest value.
This isn't a great solution but it is simple, ContainsKey is an O(1) lookup, so you'll be at most iterating your array twice.
From a software engineering standpoint, I would expect a function called MostFreq to return the element with the highest frequency - not the frequency itself. I would switch your out and return values.
You could eliminate the sort you do at the start by iterating the entire array once, keeping a count of how many times you come across each value in a temporary array, and then iterating the temporary array for the highest number. You could keep both the highest frequency count and the most frequent item throughout, too.
Different sorts have different efficiencies on different types of data, of course, but this would be a worst case of just two iterations.
Edit: Apologies for the repeat... 'Tweren't there when I started :)
Done in 1 pass....
public class PopularNumber
{
private Int32[] numbers = {5, 4, 3, 32, 6, 6, 3, 3, 2, 2, 31, 1, 32, 4, 3, 4, 5, 6};
public PopularNumber()
{
Dictionary<Int32,Int32> bucket = new Dictionary<Int32,Int32>();
Int32 maxInt = Int32.MinValue;
Int32 maxCount = 0;
Int32 count;
foreach (var i in numbers)
{
if (bucket.TryGetValue(i, out count))
{
count++;
bucket[i] = count;
}
else
{
count = 1;
bucket.Add(i,count);
}
if (count >= maxCount)
{
maxInt = i;
maxCount = count;
}
}
Console.WriteLine("{0},{1}",maxCount, maxInt);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MostFrequentElement
{
class Program
{
static void Main(string[] args)
{
int[] array = new int[] { 4, 1, 1, 4, 2, 3, 4, 4, 1, 2, 4, 9, 3, 1, 1, 7, 7, 7, 7, 7 };
Array.Sort(array, (a, b) => a.CompareTo(b));
int counter = 1;
int temp=0 ;
List<int> LOCE = new List<int>();
foreach (int i in array)
{
counter = 1;
foreach (int j in array)
{
if (array[j] == array[i])
{
counter++;
}
else {
counter=1;
}
if (counter == temp)
{
LOCE.Add(array[i]);
}
if (counter > temp)
{
LOCE.Clear();
LOCE.Add(array[i]);
temp = counter;
}
}
}
foreach (var element in LOCE)
{
Console.Write(element + ",");
}
Console.WriteLine();
Console.WriteLine("(" + temp + " times)");
Console.Read();
}
}
}
Here's an example how you could do it without LINQ and no dictionaries and lists, just two simple nested loops:
public class MostFrequentNumber
{
public static void Main()
{
int[] numbers = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
int counter = 0;
int longestOccurance = 0;
int mostFrequentNumber = 0;
for (int i = 0; i < numbers.Length; i++)
{
counter = 0;
for (int j = 0; j < numbers.Length; j++)
{
if (numbers[j] == numbers[i])
{
counter++;
}
}
if (counter > longestOccurance)
{
longestOccurance = counter;
mostFrequentNumber = numbers[i];
}
}
Console.WriteLine(mostFrequentNumber);
//Console.WriteLine($"occured {longestOccurance} times");
}
}
You get the value of the most frequently occurring number, and (commented) you could get also the numbers of the occurrences.
I know I have an "using Linq;", that's just to convert the initial input string to an int array and to spare a couple of lines and a parsing loop. Algorithm is fine even without it, if you fill the array the "long" way...
Lets suppose the array is as follows :
int arr[] = {10, 20, 10, 20, 30, 20, 20,40,40,50,15,15,15};
int max = 0;
int result = 0;
Map<Integer,Integer> map = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
if (map.containsKey(arr[i]))
map.put(arr[i], map.get(arr[i]) + 1);
else
map.put(arr[i], 1);
int key = map.keySet().iterator().next();
if (map.get(key) > max) {
max = map.get(key) ;
result = key;
}
}
System.out.println(result);
Explanation:
In the above code I have taken HashMap to store the elements in keys and the repetition of the elements as values. We have initialized variable max = 0 ( max is the maximum count of repeated element) While iterating over elements We are also getting the max count of keys.
The result variable returns the keys with the mostly repeated.
int[] arr = { 4, 5, 6, 4, 4, 3, 5, 3 };
var gr = arr.GroupBy(x => x).OrderBy(x => x.Count()).Last();
Console.WriteLine($"The most Frequent Item = {gr.Key} with frequency = {gr.Count()}"); // The most Frequent Item = 4 with frequency = 3
int[] numbers = new int[] {1, 2, 3, 2, 1, 4, 2};
Dictionary<int, int> numberCounts = new Dictionary<int, int>();
foreach (int number in numbers)
{
if (numberCounts.ContainsKey(number))
{
numberCounts[number]++;
}
else
{
numberCounts[number] = 1;
}
}
int maxCount = numberCounts.Values.Max();
int mostFrequentNumber = numberCounts.Where(x => x.Value == maxCount).OrderByDescending(x => x.Key).First().Key;
Console.WriteLine("Most frequent number: " + mostFrequentNumber);
int count = 1;
int currentIndex = 0;
for (int i = 1; i < A.Length; i++)
{
if (A[i] == A[currentIndex])
count++;
else
count--;
if (count == 0)
{
currentIndex = i;
count = 1;
}
}
int mostFreq = A[currentIndex];

Categories

Resources