Linq with "where in" clause on collections - linq

I have 2 lists [Collections ]
Example:
ListA is having 100 string keys
ListB is having 50 string Keys
Now i want to write one linq query on ListA where i want to find common keys which are in ListB
Please help

Take this for example:
//Define 2 Lists
var ListA = new List<string>();
var ListB = new List<string>();
for(int i = 0; i < 100; i++)
{
//if counter smaller 50 add to both lists
if(i < 50)
{
ListA.Add("Value"+i);
ListB.Add("Value"+i);
}
//add only to listA
else
ListA.Add("Value"+i);
}
//ListA ranges from 0 to 99
//ListB ranges from 0 to 49
var result = ListA.Intersect(ListB);
The output of result will be an IEnumerable<string> with values ranging from Value0 to Value49 since those are the keys which are in both Lists.

Related

Generate unique random numbers in Dart

How can I generate two different random numbers in dart?
I have generated two random numbers using code below.
int rand1 = Random().nextInt(16);
int rand2 = Random().nextInt(16);
if(rand1 == rand2)
// generate new random
How do I generate new random numbers until rand1 != rand2?
If you need to have two different random numbers in a fixed range, then the simplest approach would be:
var random = Random();
var n1 = random.nextInt(16);
var n2 = random.nextInt(15);
if (n2 >= n1) n2 += 1;
This ensures that the first number can assume all 16 values, and the second number can assume any of the remaining 15 values, and with as even a distribution as the random generator allows.
For two ordered distinct numbers in the range 0..15, there are 16 * 15 possible outcomes, and you probably want each outcome to be equally probable.
This code achieves this by picking the first number at random, and then picking the second number to be one of the numbers different from the first by ensuring that it is in either the range [0 .. (n1 - 1)] or the range [(n1 + 1) .. 15] ... by picking a number in the range [0 .. 14] and adding one if >= n1, shifting the range [n1 .. 14] into [(n1 + 1) .. 15].
You can do this for more numbers, but you have to do more tests and additions.
I would suggest you a different approach, looping can be pain.
// create a list say of 16 numbers.
List list = List.generate(16, (i) => i);
// shuffle it
list.shuffle();
// take the numbers now, they are always unique
int firstRandonNum = list[0];
int secondRandonNum = list[1];
This is the simplest way to do it:
import 'dart:math';
void main() {
int rand1 = Random().nextInt(16);
int rand2 = Random().nextInt(16);
while(rand1 == rand2){
rand1 = Random().nextInt(16);
rand2 = Random().nextInt(16);
}
print('$rand1 $rand2');
}
To generate any 5 unique random numbers under a range 0-49
List<int> numberList = [];
Random randomizer = new Random();
while (numberList.length < 5) {
int random_number = randomizer.nextInt(50);
if (!numberList.contains(random_number)) {
numberList.add(random_number);
}
}
A potential solution for pulling many out of many (say, 50 out of thousands) is to loop and memoize with a hash set.
I pulled this from my code, but something like:
var hashSet = HashSet();
for (var i = 0; i < boardSize; i++) {
words.add([]);
for (var j = 0; j < boardSize; j++) {
Random _random = new Random();
String wordToAdd = abstractPossibleWords[_random.nextInt(abstractPossibleWords.length)];
while (hashSet.contains(wordToAdd)) {
wordToAdd = abstractPossibleWords[_random.nextInt(abstractPossibleWords.length)];
}
words[i].add(wordToAdd);
}
}
maybe useful for you.
'max' is exclusive. the unique result number is in the return List.
List<int> getRandomNums(int countOfNum, int max) {
int num = 0;
List<int> numList = [];
var random = Random();
int i = 0;
while ( i < countOfNum) {
int oldNum = num;
num = random.nextInt(max);
if (numList.contains(num)) continue;
numList.add(num);
i++;
}
return numList;
}

Sort the Array and move all the repeated Elements to End

I have encountered this question in my recent interview.
An array is given, I need to sort the array and all the duplicate elements should be at the end.
Example:
input: {7,4,2,3,3,5,3,11,9,2}
Since 2 & 3 are repeated elements they should occur at the end of Array.
Output: {4,5,7,9,11,2,2,3,3,3}
I am free to use any other data structure. No constraints.
CREATE_ARRAY repeated, unique
SORT inputArray
ADD MINIMAL_POSSIBLE_VALUE TO inputArray
TRAVERSE inputArray i=index (from 2nd element to last):
IF inputArray[i-1] == inputArray[i]:
2X: ADD inputArray[i] TO repeated
i++
WHILE i < LENGTH(inputArray) - 1 and inputArray[i-1] == inputArray[i]:
ADD inputArray[i] TO repeated
i++
ELSE:
ADD inputArray[i-1] TO unique
PRINT MERGED(unique, repeated)
You will be sorting your array so duplicate values form patches. You will then distribute the array to unique values array and repeated values array and print them both.
The third line ADD MINIMAL_POSSIBLE_VALUE TO inputArray just adds a dummy element to the array that will never get printed but saves you some IF statements.
// algorithm
function algorithm(input) {
input.sort(function(a, b) { return a - b });
input.push(Number.MIN_VAL);
var repeated = [], unique = [];
for (var i = 1; i < input.length; i++) {
if (input[i - 1] == input[i]) {
repeated.push(input[i], input[i]);
i++;
while (i < input.length - 1 && input[i - 1] == input[i]) {
repeated.push(input[i]);
i++;
}
} else {
unique.push(input[i - 1]);
}
}
return unique.concat(repeated);
}
// driver
inputBox = document.getElementById('input-box');
outputBox = document.getElementById("output-box");
inputBox.addEventListener("keyup", function() {
outputBox.innerHTML = algorithm(inputBox.value.split(/[\s,]+/).map(Number));
});
<input id="input-box">
<div id="output-box"></div>
Solution with C# using the sort method of List
static void Main(string[] args)
{
List<int> list = new List<int> { 7, 4, 2, 3, 3, 5, 3, 11, 9, 2, 5 };
List<int> tmp = new List<int> { };
List<int> rep = new List<int> {};
//sorting the list
list.Sort();
for (var i = 0; i < list.Count(); i++)
{
int cantidad = list.LastIndexOf(list[i]) - list.IndexOf(list[i]);
if ( cantidad != 0)
{
//found repetitions
rep.AddRange(list.GetRange(list.IndexOf(list[i]), cantidad + 1));
i += cantidad;
}
else tmp.Add(list[i]);
}
tmp.AddRange(rep);
foreach (int data in tmp)
Console.WriteLine(data);
Console.ReadLine();
}
Solution with C# sorting out manually
static void Main(string[] args)
{
List<int> list = new List<int> { 7, 4, 2, 3, 3, 5, 3, 11, 9, 2 };
List<int> tmp = new List<int> {};
List<int> rep = new List<int> {};
foreach (int data in list)
{
if (tmp.Count() > 0)
{
int posicion = -1;
bool bandera = false;
for (var i=0; i < tmp.Count(); i++)
{
//searching a repetition
if (tmp[i] == data)
{
tmp.RemoveAt(i);
//adding to the repeated list at the end or in a determined position
for (var j = 0; j < rep.Count(); i++)
{
if (rep[j] > data)
{
bandera = true;
rep.Insert(j, data); //the one that was deleted
rep.Insert(j, data); //the one at the original list
break;
}
}
if (!bandera)
{
bandera = true;
rep.Add(data); //the one that was deleted
rep.Add(data); //the one at the original list
}
break;
}
//saving the position to be inserted
if (tmp[i] > data)
{
posicion = i;
break;
}
}
//was not a repetition
if (!bandera)
{
bool banderaRep = false;
//searching in the repeated list
for (var i = 0; i < rep.Count(); i++)
{
if (rep[i] == data)
{
banderaRep = true;
rep.Insert(i, data);
break;
}
}
//was not in the repeated list
if (!banderaRep)
{
if (posicion == -1)
tmp.Add(data);
else
tmp.Insert(posicion, data);
}
}
}
else
tmp.Add(data);
}
//join
tmp.AddRange(rep);
foreach (int data in tmp)
Console.WriteLine(data);
Console.ReadLine();
}
Solution using a map data structure, not a very efficient solution but it works nonetheless:
1> Traverse through the vector counting frequency of numbers in a map
2> Iterate over the map (elements will be in sorted order) pushing unique elements in a vector and repeated elements in another vector
3> Push repeated elements in the sorted array
Code in C++
vector<int> sortUnique(const vector<int> & nums) {
// Step 1
map<int, int> numFreq;
for (auto it : nums) {
if (numFreq.count(it) == 0) {
numFreq[it] = 1;
}
else {
numFreq[it]++;
}
}
// Step 2
vector<int> sorted;
sorted.reserve(nums.size());
vector<int> repeated;
repeated.reserve(nums.size());
for (auto it : numFreq) {
if (it.second == 1) {
sorted.push_back(it.first);
}
else {
for (int i = 0; i < it.second; i++) {
repeated.push_back(it.first);
}
}
}
// Push repeated elements at the end
for (auto it : repeated) {
sorted.push_back(it);
}
return sorted;
}
I will use Swift 3 (beta 3) to describe an high level implementation for your problem.
let list = [7,4,2,3,3,5,3,11,9,2]
let countedSet = NSCountedSet(array: list)
let singles = list.filter { countedSet.count(for: $0) == 1 }
let duplicates = list.filter { countedSet.count(for: $0) > 1 }
let res = singles.sorted() + duplicates.sorted()
Line #2
This class creates an index, it associate to each value it number of occurrencies.
Lines #3 and #4
Here I am filtering the original array. I am putting into singles the values with only 1 occurrences and into duplicates the values that appear more then once.
Line #5
Finally I sort singles and duplicates and I concatenate them
You can do this with a dictionary of values with associated counts. You didn't specify a language, so I'll give you some pseudo code.
Note This does not result in sorted output.
First, scan the array and create your dictionary of values and counts:
dict = create new dictionary
for each item in array
if dict contains item
increase count for that item in the dictionary
else
add item to dictionary with count of 1
Now create two indexes: one starting at 0, and other at (array.length - 1). For each item in the dictionary, if it is a single, write it at the front of the array. Otherwise write count items at the back of the array. Like this:
frontIndex = 0
backIndex = array.Length - 1
for each item in dictionary
if item.count == 1
array[frontIndex] = item
frontIndex = frontIndex + 1
else
for i = 0 to item.Count-1
array[backIndex-i] = item
backIndex = backIndex - item.Count
Time is O(n) to build the dictionary, and O(n) to repopulate the array. Extra space is O(n).

How to arrange 2 lists in 2 grids of equal number of columns?

I have 2 lists of icons, that need to be arranged in 2 grids.
How do I work out the number of columns for the grids, so that
in each grid there are an equal number of columns.
The number of rows is irrelevant.
The columns should not exceed a maximum (e.g. 6 columns)
The display is a wide desktop monitor, so a wide grid is preferred over a long grid (see example below)
Example 1
list1: 7 items
list2: 4 items
=> use 4 columns,
list1 2 rows by 4 columns (2nd row only partially full),
list2 1 row by 4 columns
Example 2
list1: 100 items
list2: 5 items
=> use 5 columns,
list1: 20 rows by 5
list2: 1 row by 5 columns
Example 3 (Wide grid vs. long grid)
list1: 2 items
list2: 8 items
=>
Long grid: 2 columns in each grid (not preferred)
Wide grid: e.g. 4 columns in each grid (preferred)
Here is my attempt in C#. There are comments in the code but basically there are 3 steps.
For each icon-list get a list of all possible columns (i.e. 1 up to the length of the shortest icon-list)
Find the best column in both lists (i.e. where the difference between the columns is smallest)
Because there could be multiple best columns, find the best-best column
public int GetIdealNumColumns(int s1, int s2)
{
const int maxCol = 6; //maximum number of columns
if (s1 == s2) { return maxCol; }
//STEP 1 -------------------------------------------------
//get all possible columns for both lists
int gcd = GCD(s1, s2);
int range = Math.Min(Math.Min(s1, s2),maxCol);
var cols1 = Enumerable.Range(1, range).ToList();
var cols2 = Enumerable.Range(1, range).ToList();
// -------------------------------------------------
//STEP 2 -------------------------------------------------
//go through both lists and find the best #columns -> this is N^2
int bestDiff = int.MaxValue;
//there could be multiple equal column numbers between the 2 lists
//so use 2 lists to store the results
List<int> bestCols1 = new List<int>();
List<int> bestCols2 = new List<int>();
for (int i1 = 0; i1 < cols1.Count; i1++)
{
for (int i2 = 0; i2 < cols2.Count; i2++)
{
//difference between the number of columns
int diff = Math.Abs(cols1[i1] - cols2[i2]);
//the smaller the difference the better
if (diff < bestDiff)
{
bestDiff = diff;
//reset the lists
bestCols1 = new List<int>();
bestCols2 = new List<int>();
bestCols1.Add(i1);
bestCols2.Add(i2);
}
else if (diff == bestDiff) //difference equal => store
{
bestCols1.Add(i1);
bestCols2.Add(i2);
}
}
}
// -------------------------------------------------
//STEP 3 -------------------------------------------------
//now go through the best results and find the result that
//is closest to the max-number-of-columns
bestDiff = int.MaxValue;
int best = 0;
if (bestCols1.Count > 1)
{
for (int i = 0; i < bestCols1.Count; i++)
{
//get average value
int avg = (cols1[bestCols1[i]] + cols2[bestCols2[i]]) / 2;
//check how close the maxCol
int diff = Math.Abs(avg - maxCol);
if (diff < bestDiff)
{
bestDiff = diff;
best = cols1[bestCols1[i]]; //not sure if I should take avg?
}
}
}
// -------------------------------------------------
return best == 0 ? maxCol : best;
}

Printing lexicographically sorted subsets from a given string

For ex - If the string is "abc", the answer should be
a ab abc ac b bc c (Only lexicographically smallest combination from a set of characters should appear)
I have solved the problem but for string containing 15 or more characters, it is taking a lot of time. How can I reduce running time of my algorithm?
Here , n is length of string.
Here is my code:
int n = int.Parse(Console.ReadLine());
var str = Console.ReadLine();
string coll = string.Empty;
coll = coll + " " + str[0];
for (int j = 1; j < n; j++)
{
var items = coll.Split(' ');
foreach (var item in items)
{
coll = coll + " " + item+str[j];
}
}
var tt = coll.Split(' ').OrderBy(a => a);
foreach (var item in tt)
if (!string.IsNullOrEmpty(item))
Console.WriteLine(item);
For a string of length n, there are 2^n possible subsets. If each of the subsets needs to be printed, you can't get around the exponential complexity.

Nested loop complexity

I have several lists of varying size, each index of the list contains both a key and an object : list1.add('Key', obj).
The lists are all sorted.
My aim is to iterate through the list and match 1 or more items in list 2,3,4 or n to an item in the mainList using the key.
Currently I do something along the lines of:
for i to list1 size
for j to list2 size
if list1[i] = list2[j]
do stuff
As I loop through I'm, using boolean values to exit quickly using a if current != previous check and I'm deleting the object from the list I take it from.
it's working fine but I now have another list that I need to match and possible another n lists afterwards. The lists are of different sizes.
the 2 options that I can see are to either repeat the above segment of code several times where the inner list is changed - I do no like this approach.
The other option is to extend the above and once one inner loop is finished, move onto the next:
for i to list1 size
for j to list2 size
if list1[i] = list2[j]
do stuff
for k to list2 size
if list1[i] = list2[k]
do stuff
I'd like to think I'm correct in thinking that the 2nd is more efficient however I'm unsure. Also, is there a better way?
Thanks for any advice / help.
If the lists are all sorted then you only need to iterate though each list once; on each iteration of the main list, iterate through a secondary list (starting at the previously saved index, initialized to 0) until you find an index whose value is greater than the current value of the main list, save this index, and proceed to the next secondary list.
Array<Integer> indices = new Array(n-1); // indices for every list except list1
for(int i = 0; i < indices.size; i++) {
indices[i] = 0;
}
for(int i = 0; i < list1.size; i++) {
Value curVal = list1[i];
while(indices[0] < list2.size && list2[indices[0]] <= curVal) {
if(list2[indices[0]] == curVal) {
// do stuff on list2[indices[0]]
}
indices[0]++;
}
while(indices[1] < list3.size && list3[indices[1]] < curVal) {
if(list3[indices[1]] == curVal) {
// do stuff on list3[indices[1]]
}
indices[1]++;
}
// etc
}
You can avoid the copy-pasting by using something like a ListIterator that contains a list and its current index; then on each iteration of the main loop you'll iterate through a list of ListIterators in lieu of the copy-pasted code block
public class ListIterator {
int index = 0;
List<Value> list;
Value curVal() {
return list[index];
}
boolean hasNext() {
return (index < list.size);
}
}
List<ListIterator> iterators;
for(int i = 0; i < list1.size; i++) {
Value curVal = list1[i];
for(int j = 0; j < iterators.size; j++) {
ListIterator iterator = iterators[j];
while(iterator.hasNext() && iterator.curVal() <= curVal) {
if(iterator.curVal() == curVal) {
// do something with iterator.curVal()
}
iterator.index++;
}
}
}
This is time complexity O(n) where n is the sum of the lengths of all of your lists
Edit: If it's difficult to compare keys via <=, then you can use a Set implementation instead. Add the List1 keys to a Set, then iterate through the remaining lists testing for set membership.
Set<String> set = new Set(List1);
Array<List> lists = new Array();
// add lists to Array<List>
for(int i = 0; i < lists.size; i++) {
List currentList = lists[i];
for(int j = 0; j < currentList.size; j++) {
if(set.contains(currentList[j]) {
// do something
}
}
}

Resources