How can I get the difference from 2 arrays
Input:
List<Integer> bookingList = (3,4,5,6,5,5);
List<Integer> bookedList = (1,2,3,2,3,4);
What I want to do is pointwise subtraction
bookingList.get(i) - bookedList.get(j)
//i is the position
//j is the position
The result should be a new List with the following content:
List<Integer> finalList = (2,2,2,4,2,1)
Here you are:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
caluclateFinalList();
}
private static void caluclateFinalList() {
List<Integer> bookingList = new ArrayList<>(Arrays.asList(3, 4, 5, 6, 5, 5));
List<Integer> bookedList = new ArrayList<>(Arrays.asList(1, 2, 3, 2, 3, 4));
// Output list
List<Integer> finalList = new ArrayList<>(bookingList.size());
// Loop
for (int position = 0; position < bookedList.size(); position++) {
// Calculate result
int result = bookingList.get(position) - bookedList.get(position);
// Add result to final list
finalList.add(result);
}
// Print final list to the console
System.out.println(finalList);
}
}
If the lists are guaranteed to be the same size then you can simply do a for loop.
List<Integer> results = new ArrayList(bookingList.size());
for(int i= 0; i < bookingList.size(); i++) {
results.add(bookingList.get(i) - bookedList.get(i));
}
return results;
This gives you the differences inside results and within O(n) where n is the size of the arrays.
If the arrays are not the same size, you obviously need to check for some index bounds. I'm not sure whether you want to consider the excess elements and just add them to the result, or if you want to discard them, but a simple modification to the algorithm above can get your there.
Related
I have got two arraylists :
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(5);
numbers.add(2);
numbers.add(0);
numbers.add(0);
numbers.add(8);
ArrayList<String> linkers = new ArrayList<>();
linkers.add("five");
linkers.add("two");
linkers.add("zero");
linkers.add("zero");
linkers.add("eight");
I need to sort the numbers list in ascending order and get the linkers list sorted in the same order.
Assuming there is a one-to-one mapping of the number to their name you can do it like so. Just sort the indices based on the list of numeric numbers. Then use those indices to get each list's values in the proper, sorted order. Here, I just print them to show the results.
List<Integer> indices = IntStream.range(0, numbers.size()).boxed()
.sorted(Comparator.comparing(numbers::get)).toList();
for (int i : indices) {
System.out.println(numbers.get(i) + " " + linkers.get(i));
}
prints
0 zero
0 zero
2 two
5 five
8 eight
They could be "sorted" as follows:
numbers = indices.stream().map(numbers::get).toList();
linkers = indices.stream().map(linkers::get).toList();
System.out.println(numbers);
System.out.println(linkers);
prints
[0, 0, 2, 5, 8]
[zero, zero, two, five, eight]
Parallel lists/arrays are trouble. Put corresponding elements into combined objects, then sort those.
import java.util.ArrayList;
import java.util.Comparator;
class Pair {
public int i;
public String s;
public Pair(int _i, String _s) {
i = _i;
s = _s;
}
}
class Test {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(5);
numbers.add(2);
numbers.add(0);
numbers.add(0);
numbers.add(8);
ArrayList<String> linkers = new ArrayList<>();
linkers.add("five");
linkers.add("two");
linkers.add("zero");
linkers.add("zero");
linkers.add("eight");
ArrayList<Pair> pairs = new ArrayList<>();
for (int i = 0; i < 5; i++) {
pairs.add(new Pair(numbers.get(i), linkers.get(i)));
}
pairs.sort(new Comparator<Pair>() {
public int compare(Pair a, Pair b) {
if (a.i == b.i) return 0;
else if (a.i < b.i) return -1;
else return 1;
}
});
for (int i = 0; i < 5; i++) {
System.out.println(pairs.get(i).s);
}
}
}
One possibility would be to group each number (int) with its name (String) in a class (Java < 15) or record (Java >= 15):
record NumberWithName(int value, String name) {
}
Then, for each pair of int and String from the two Lists, construct a Number-instance and add it to a new List numbersWithName:
List<Integer> values = List.of(5, 2, 0, 0, 8);
List<String> names = List.of("five", "two", "zero", "zero", "eight");
List<NumberWithName> numbersWithName = new ArrayList<>();
for (int index = 0; index < values.size(); ++index) {
numbersWithName.add(new NumberWithName(values.get(index), names.get(index)));
}
Finally, we sort this List with a corresponding Comparator and print the result:
numbersWithName.sort(Comparator.comparing(NumberWithName::value));
System.out.println(numbersWithName);
This produces the following output:
[NumberWithName[value=0, name=zero], NumberWithName[value=0, name=zero], NumberWithName[value=2, name=two], NumberWithName[value=5, name=five], NumberWithName[value=8, name=eight]]
A TreeMap should help here where your key is the integer and the value represents the string. TreeMap is directly sorted by the key.
I have an arraylist with 2 objects inside and i Need muiltplicate N times the last of them.
Exemple.
Arraylist = [Z0123,Z0321]
I need this result
ArrayList = [Z0123,Z0321,Z0321,Z0321,N...]
I'm trying with the last element, but this dosn't work with N elements
for(int i = 0; i < statusCorrigido.size(); i++) {
int tamanho = statusCorrigido.size()-1 ;
listaFinal.add(statusCorrigido.get(i));
listaFinal.add(statusCorrigido.get(tamanho));
}
You can use addAll with Collections.nCopies.
List<String> list = new ArrayList<>(Arrays.asList("Z0123", "Z0321"));
int n = 5;
list.addAll(Collections.nCopies(n - 1, list.get(list.size() - 1)));
System.out.println(list); // [Z0123, Z0321, Z0321, Z0321, Z0321, Z0321]
You can do it recursively, see i'll show you how:
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList array = new ArrayList();
array.add(5);
array.add(2);
System.out.println(addElement(5, array));
}
public static ArrayList addElement(int stopCondition, ArrayList array){
if (stopCondition == 0){
return array;
}
array.add(array.get(array.size()-1));
stopCondition--;
return addElement(stopCondition, array);
}
}
Output:
[5, 2, 2, 2, 2, 2, 2]
You cannot change the list while looping throught it!
Firstly get the last item and then add it to the list.
Object copy = list.get(list.size() - 1);
for(int i = 0; i < N; i++)
list.add(copy)
I want to count number of elements and remove some if they meet a criterion. Removing using collect and removeAll doesn't work since it removes all equal elements and I want to remove a range not all.
I tried to use sublist.clear() but I get ConcurrentModificationException even though I'm using it.remove().
public static List<Integer> controlOccurrences(List<Integer> sortedArr, int m) {
int writelndex = 0, count=1;
List<List<Integer>> toRemove = new ArrayList<>();
for (int i = 1; i < sortedArr.size(); ++i) {
if (sortedArr.get(i-1).equals(sortedArr.get(i))) {
count++;
} else {
if(count == m) {
int nCopies = Math.min(2,m);
List<Integer> c = sortedArr.subList(writelndex + nCopies, i);
toRemove.add(c);
}
count = 1;
writelndex = i;
}
}
Iterator<List<Integer>> iterator = toRemove.iterator();
while (iterator.hasNext()) {
List<Integer> integers = iterator.next();
iterator.remove();
integers.clear();
}
return sortedArr;
}
EDIT: adding an example:
Lets say we have the following list: (1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5) and m = 3. This means that all numbers that occur m times should occur 2 times (Math.min(2,3)). So the expected result is (1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 5).
EDIT 2: #ShubhenduPramanik Solved the task very elegantly.
However, it's still unclear to me why ConcurrentModificationException was thrown even though I was using iterator.remove() and how would you go about removing a sublist from a list while iterating over it.
Hope this helps:
static List<Integer> controlOccurrences(List<Integer> sortedArr, int m) {
//make the count of each element
Map<Integer, Long> result = sortedArr.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
for (Map.Entry<Integer, Long> entry : result.entrySet()) {
if (entry.getValue() == m) {
// Here 2 is hard coded. You can make a variable and pass it to the method with a parameter
for (int i = 0; i < m - 2; i++)
{
sortedArr.remove(entry.getKey());
}
}
}
return sortedArr;
}
N.B: This code is not perfect as I've assumed that m>=2
If I correctly understood the task then the algorithm:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) throws IOException {
int m = 3;
BufferedReader reader = new BufferedReader(
new InputStreamReader(System.in));
int numbers;
List<Integer> sortedList = new ArrayList<>();
// Fill in the list with values
for (int i = 0; i < 13; i++) {
numbers = Integer.parseInt(reader.readLine());
sortedList.add(numbers);
}
System.out.println(controlOccurrences(sortedList, m));
}
public static List<Integer> controlOccurrences(List<Integer> sortedArr, int m) {
int count= 1;
for (int i = 0; i < sortedArr.size(); i++) {
for (int j = 0; j < sortedArr.size(); j++) {
if (sortedArr.get(i).equals(sortedArr.get(j)) && i != j) {
count += 1;
}
}
if (count == m) {
sortedArr.remove(i);
count = 1;
} else {
count = 1;
}
}
return sortedArr;
}
}
To get the most optimized solution, you should:
1. Build a list (or set) of the indices of the values to remove
2. Move values of your original list to a new one, except the one at the listed indices.
3. Return the new list.
This way, your algorithm complexity is O(2n), which is more optimized than both previous answers. Plus, you keep given list untouched (which can be recommended according to your execution context). Last advantage, the copy is favored because each remove call on a list is potentially heavy (inner objects after removed index are moved to the left: partial hidden browsing -_- )
I won't directly give you a working code, to let you practice ;).
Note: your use-case is too complex for it, but you should look at List.removeIf() code of array list API, which is really well optimized. Here is an article talking about it: advantages of removeIf method
I have a programming assignment where I am tasked with the following:
I am taking two int values (x and y) and creating two different arrays: the first (size x) will print an array starting from x and descending down to 1. The second (size y) will take random values from the first array (size x) and store it in its own array. I will then print out the second array. However, the second array cannot have any repeating values. For example, if the array was size 10, it could not have two of the same digit within its 10 individual indexes. I am attempting to store unique elements in my second array by creating two arrays, one boolean to check for unique elements and another one to store those unique elements. Here is my code:
/*
* user will enter desired size x for first array labeled arr_1
* arr_1 will contain values descending from x down to 1
* user will enter desired size y for second array labeled arr_2
* arr_2 will contain random values taken from arr_1 w/o repeating numbers
*/
import java.util.Arrays;
// import java.util.Arrays;
import java.util.Random;
// import java.util.Scanner;
public class Prog1B
{
public static void main(String[] args)
{
System.out.println("Program 1B, Christopher Moussa, masc1574");
// Scanner scnr = new Scanner(System.in);
int x = 20;
int v = x;
int[] arr_1 = new int[x];
for (int i = x-1; i >= 0; i--)
{
arr_1[i] = v; // System.out.print(i+1 + " "); prints 20, 19, ... , 1
v--; // System.out.print(arr_1[i] + " "); prints 20, 19, ... , 1
}
// int[] b = unique(arr_1);
System.out.println(Arrays.toString(unique(arr_1)));
}
public static int[] unique (int[] n)
{
boolean[] seen = new boolean[n.length];
int[] unique = new int[n.length];
Random rand = new Random(123L);
for (int i = 0; i < n.length; i++)
{
int index = rand.nextInt(n.length);
while (seen[index])
{
index = rand.nextInt(n.length);
}
unique[i] = n[index];
}
return unique;
}
}
The code compiles and runs, but it still prints out an array with repeating values. I am trying to write the program so that it does not print out an array with repeating values, only unique values. Do you have any suggestions as to where the problem lies? I am pretty sure it lies within the "unique" method, more specifically when the boolean array is checking for unique values (I noticed while trying to debug that even if the random index it generated was not unique, it still skipped the while condition and printed it out). I am a beginning programmer (a freshman at San Diego State studying computer science) and any feedback/advice will be greatly appreciated. Thanks you very much.
I found the problem in your code. You never update your "seen" Boolean array. See the code below for fix:
public static int[] unique (int[] n){
boolean[] seen = new boolean[n.length];
int[] unique = new int[n.length];
Random rand = new Random(123L);
for (int i = 0; i < n.length; i++)
{
int index = rand.nextInt(n.length);
while (seen[index])
{
index = rand.nextInt(n.length);
}
seen[index] = true; //boolean array updated
unique[i] = n[index];
}
return unique;
}
Using this fix, I was able to get the output below (which has no repeats):
[3, 11, 17, 10, 16, 18, 15, 6, 14, 20, 7, 13, 1, 19, 9, 2, 5, 4, 12, 8]
You need to even set your array seen[index] = true;
public static int[] unique (int[] n)
{
boolean[] seen = new boolean[n.length];
int[] unique = new int[n.length];
Random rand = new Random(123L);
for (int i = 0; i < n.length; i++)
{
int index = rand.nextInt(n.length);
while (seen[index])
{
index = rand.nextInt(n.length);
}
unique[i] = n[index];
seen[index] = true;
}
return unique;
}
Unless you specifically have to do it this way, I suggest you take a step back and try a totally different approach, something like this:
Set<int> mySet = new HashSet<int>(Arrays.asList(someArray));
NOTE: You will want to adjust the return type of unique() to be Set
The rest of the implementation is left as an excercise for the reader. Basically you take the array and convert it to a set as the example above.
(Credit where credit is due)
I just wanted to steer you in the right direction per https://meta.stackexchange.com/questions/10811/how-do-i-ask-and-answer-homework-questions
Good luck, I would say the biggest lesson here is how to walk away from code that has become inefficient when a better solution exists. Good luck!
Heres is how to do this using java8 lambdas
ArrayList<Integer> arrayli = new ArrayList<Integer>(Arrays.asList(arr_1));//converted array to list
System.out.println();
List<Integer> distinctIntegers = arrayli.stream().
.distinct()
.boxed()
.collect(Collectors.toList());
distinctIntegers.foreach(System.out::println);
I have a list of integer arrays. I need to find the common elements between those. What I can think of is an extension of what is listed in Common elements in two lists
Example would be
[1,3,5],
[1,6,7,9,3],
[1,3,10,11]
should result in [1,3]
There are no duplicates in the arrays as well.
Is there a straight forward way to do this?
You can transform the lists to sets, and then use Set.retainAll method for intersection between the different sets.
Once you intersect all sets, you are left with the common elements, and you can transform the resulting set back to a list.
You can use Set's intersection method offered by Guava, Here is a little example :
public <T> Set<T> intersection(List<T>... list) {
Set<T> result = Sets.newHashSet(list[0]);
for (List<T> numbers : list) {
result = Sets.intersection(result, Sets.newHashSet(numbers));
}
return result;
}
Hope that could help you
We can use retainAll method of Collections. I initialised my commons arraylist with the first array list and called this for each remaining arraylists.
List<List<Integer>> lists = new ArrayList<List<Integer>>();
lists.add(new ArrayList<Integer>(Arrays.asList(1, 3, 5)));
lists.add(new ArrayList<Integer>(Arrays.asList(1, 6, 7, 9, 3)));
lists.add(new ArrayList<Integer>(Arrays.asList(1, 3, 10, 11)));
List<Integer> commons = new ArrayList<Integer>();
commons.addAll(lists.get(1));
for (ListIterator<List<Integer>> iter = lists.listIterator(1); iter.hasNext(); ) {
commons.retainAll(iter.next());
}
System.out.println(commons);
System.out.println(lists.get(1));
with Java 8
ArrayList retain = list1.stream()
.filter(list2::contains).filter(list3::contains).collect(toList())
If you are looking for a function that returns elements that exist in all lists,
then the straight forward & simple way is building a statistic { < member, occurences > }
The condition here is no duplicates among the same list,
private Set<Integer> getCommonElements(ArrayList<Integer[]> idList)
{
MapList<Integer,Short> stat = new MapList<Integer,Short>();
// Here we count how many times each value occur
for (int i = 0; i < idList.size(); i++)
{
for (int j = 0; j < idList.get(i).size; j++)
{
if (stat.containsKey(idList.get(i)[j]))
{
stat.set(idList.get(i)[j], stat.get(idList.get(i)[j])+1);
}
else
{
stat.add(idList.get(i)[j], 1);
}
}
}
// Here we only keep value that occured in all lists
for (int i = 0; i < stat.size(); i++)
{
if (stat.get(i) < idList.size())
{
stat.remove(i);
i--;
}
}
return stat.keySet();
}
public class ArrayListImpl{
public static void main(String s[]){
ArrayList<Integer> al1=new ArrayList<Integer>();
al1.add(21);al1.add(23);al1.add(25);al1.add(26);
ArrayList<Integer> al2=new ArrayList<Integer>();
al2.add(15);al2.add(16);al2.add(23);al2.add(25);
ArrayList Al3=new ArrayList<Integer>();
al3.addAll(al1);
System.out.println("Al3 Elements :"+al3);
al3.retainAll(al2); //Keeps common elements of (al1 & al2) & removes remaining elements
System.out.println("Common Elements Between Two Array List:"+al3);
}
}
If you are using JAVA 8 streams. Then using stream reduce operation we can achieve the same.
Considering your example: Let's say
a = [1,3,5], b = [1,6,7,9,3] and c = [1,3,10,11]
List<Integer> commonElements = Stream.of(a,b,c)
.reduce((s1,s2) -> {
s1.retainAll(s2);
return s1;
}).orElse(Collections.emptyList());
Keep in mind that after running this operation a will get modified with common values as well. So you will lose the actual value of a.
So elements of a and the result elements of commonElements will be essentially the same after running this operation.
Giving some another alternative code using retainAll capability of Set
public List getCommonItems(List... lists) {
Set<Integer> result = new HashSet<>(lists[0]);
for (List list : lists) {
result.retainAll(new HashSet<>(list));
}
return new ArrayList<>(result);;
}
Usage:
List list1 = [1, 2, 3]
List list2 = [3, 2, 1]
List list3 = [2, 5, 1]
List commonItems = getCommonItems(list1, list2, list3)
System.out.println("Common items: " + result);
Result:
commonItems: [1, 2]
public class commonvalue {
Public static void MyMethod(){
Set<integer> S1 = new set<integer>{1,3,5};
Set<integer> S2 = new set<integer>{1,6,7,9,3};
Set<integer> S3 = new set<integer>{1,3,10,11};
s2.retainall(s1);
s3.retainall(s2);
system.debug(s3);
}
}