Java Multidimensional array and integer occurrences - java

I have this integer array called numList which has
[4, 4, 3, 3, 3, 2, 1, 1, 1, 1, -1, -12, -12, -12, -12]
I would like to create a multidimensional array which can store
Which left side represents the number and the right side determines the number of occurrences.
The attempt i tried... i got nowhere.
// Declaring the new multi-dimensional array.
int [] [] newArray = new int [6] [2];
// Counter 3.
int counter3 = 0;
// Get first occurrence.
while (numList[counter3] < numList.length){
for (int counter3:numList){
newArray[] ([counter3]++);
}

Assuming your numbers are in order as they are in your example numList, then you could do this:
int[] numList = { 4, 4, 3, 3, 3, 2, 1, 1, 1, 1, -1, -12, -12, -12, -12 };
int[][] newArray = new int[6][2];
int index = 0;
for (int i = 0; i < numList.length;) {
int count = 0;
for (int x = 0; x < numList.length; x++)
if (numList[x] == numList[i]) count++;
newArray[index][0] = numList[i];
newArray[index][1] = count;
index++;
i += count;
}
for (int x = 0; x < newArray.length; x++) {
for (int i = 0; i < newArray[0].length; i++)
System.out.print(newArray[x][i] + " ");
System.out.println();
}
This way, you don't have to deal with imports as in the other answers (and this is shorter), but this only works if you have ordered numbers. There are some good sorting algorithms out there, though.
Edit: I changed it so that it can take numbers in any order of any size.
int[] numList = { 6, 6, 5, 5, 4, 4, 3, 2, 1, 1, 1, 7, 6, 5, 7, 8, 65, 65, 7 };
int[][] newArray = new int[1][2];
int index = 0;
for (int i = 0; i < numList.length;) {
try {
int count = 0;
boolean isUnique = true;
for (int x = 0; x < i; x++)
if (numList[x] == numList[i]) {
isUnique = false;
break;
}
if (isUnique) {
for (int x = 0; x < numList.length; x++)
if (numList[x] == numList[i]) count++;
newArray[index][0] = numList[i];
newArray[index][1] = count;
index++;
}
i++;
} catch (ArrayIndexOutOfBoundsException e) {
int tmpArray[][] = newArray;
newArray = new int[tmpArray.length + 1][tmpArray[0].length];
for (int row = 0; row < tmpArray.length; row++)
for (int col = 0; col < 2; col++)
newArray[row][col] = tmpArray[row][col];
}
}
for (int x = 0; x < newArray.length; x++) {
for (int i = 0; i < newArray[0].length; i++)
System.out.print(newArray[x][i] + " ");
System.out.println();
}
So, at this point, it would probably be shorter to use the maps from the other answer. The only benefit of my second answer not worrying about imports.

private Map<Integer, Integer> segregateArray(List<Integer> list) {
Map<Integer, Integer> result = new HashMap<>();
for (Integer i : list) {
if (result.containsKey(i)) {
result.put(i, result.get(i) + 1);
} else {
result.put(i, 1);
}
}
return result;
}
This should work. If you still need to return array use this:
private int[][] segregateArray(int[]list) {
Map<Integer, Integer> resultHelper = new HashMap<>();
for (int i : list) {
if (resultHelper.containsKey(i)) {
resultHelper.put(i, resultHelper.get(i) + 1);
} else {
resultHelper.put(i, 1);
}
}
int[][] result = new int[resultHelper.size()][2];
int arrayIterator=0;
for(Integer key : resultHelper.keySet())
{
result[arrayIterator][0]=key;
result[arrayIterator][1]=resultHelper.get(key);
arrayIterator++;
}
return result;
}

In the real life project you probably should avoid implementing a functionality like this yourself using a low level array mechanism (you added an extensive test suite, didn't you? :) and opt for one of available libraries.
In Java 8 this can be done nicely using closures similarly to what has been described here: Count int occurrences with Java8.
In Java 7 and earlier I would use one of the collection libraries such as Guava, which contains a Multiset collection delivering exactly what you're after.

Related

Java how to copy values from 2D array to regular array row by row

I have the 2D array and printed them out backward. What I am trying to achieve is to copy each line of printed row to a regular array. Is it possible to do that?
Integer[][] testList;
testList = new Integer[][]{{1,2,3},{4,5,6},{7,8,9}, {10,11,12}};
for (int i = 0; i < testList.length; i++) {
for (int j = testList[i].length-1; j >=0; j--) {
System.out.print(testList[i][j] + " ");
}
System.out.println();
}
This will copy any size 2D array of ints.
int[][] testData = { { 1, 2, 3 },{}, null, { 4, 5, 6, 7 },null,{ 8, 9 },
{ 10, 11, 12 } };
int[] result = copy2DArrays(testData);
System.out.println(Arrays.toString(result));
prints
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
First, compute size of result array. This also handles null rows.
if a null row is encountered, replace with an empty array for copy phase.
Allocate the return array of computed size
Then for each row
iterate thru the row, copying the value to result array indexed by k
When done, return the resultant array.
public static int[] copy2DArrays(int[][] array) {
int size = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] == null) {
// replace null row with empty one
array[i] = new int[]{};
continue;
}
size += array[i].length;
}
int k = 0;
int[] result = new int[size];
for (int[] row : array) {
for (int v : row) {
result[k++] = v;
}
}
return result;
}
Another, simpler option is using streams.
stream the "2D" array
only pass nonNull rows
flatten each row into a single stream
then gather them into an array.
int[] array = Arrays.stream(testData)
.filter(Objects::nonNull)
.flatMapToInt(Arrays::stream)
.toArray();
You can create a new array and then copy the values into it:
for (int i = 0; i < testList.length; i++) {
int[] copy = new int[testList[i].length];
int copyIndex = 0;
for (int j = testList[i].length-1; j >=0; j--) {
System.out.print(testList[i][j] + " ");
copy[copyIndex++] = testList[i][j];
}
}
The Arrays class gives you a lot of nifty features:
public static void main(String[] args) {
Integer[][] testList = new Integer[][]{{1,2,3},{4,5,6},{7,8,9}, {10,11,12}};
int max = 0;
for (Integer[] row : testList) {
max = Math.max(max, row.length);
}
Integer[][] copy = new Integer[testList.length][max];
for (int i = 0; i < testList.length; i++) {
copy[i] = Arrays.copyOf(testList[i], copy[i].length);
}
for (int i = 0; i < testList.length; i++) {
System.out.println("Source " + i + ": " + Arrays.toString(testList[i]));
System.out.println("Copy " + i + ": " + Arrays.toString(copy[i]));
}
}

ArrayList Bubblesort with strings

The sorting is not working, it doesn't sort the names by the alphabet, I wrote a bubble sort algorithm with int and it worked fine. Can you help me? Is something wrong with the compareTo() method?
public ArrayList<FootballPlayer> sortByNames(ArrayList<FootballPlayer> pList)
{
FootballPlayer z;
for(int i=0; i<pList.size(); i++)
{
for(int j=0; j<pList.size()-i-1;j++)
{
if((pList.get(i).getName()).compareTo(pList.get(j+1).getName())>0)
{
z = pList.get(j);
pList.set(j, pList.get(j+1));
pList.set(j+1,z);
}
}
}
for(int i=0; i<pList.size(); i++)
{
System.out.print(pList.get(i).getName()+";");
System.out.println("");
}
return pList;
}
Your implementation is not BubbleSort! Check Bubble sort or event a bit more advanced Cocktail shaker sort.
public static void bubbleSort(List<String> pList) {
boolean done = false;
for (int i = pList.size(); !done; i--) {
done = true;
for (int j = 0; j + 1 < i; j++) {
if (pList.get(j).compareTo(pList.get(j + 1)) <= 0)
continue;
done = false;
String tmp = pList.get(j);
pList.set(j, pList.get(j + 1));
pList.set(j + 1, tmp);
}
}
}
Output:
List<String> pList = new ArrayList<>();
for (int i = 0; i < 10; i++)
pList.add(String.valueOf(i));
Collections.shuffle(pList);
System.out.println(pList); // [0, 6, 7, 9, 5, 8, 4, 1, 3, 2]
bubbleSort(pList);
System.out.println(pList); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Getting the Elements that has duplicates in an int array Java

This post - "Java + Count duplicates from int array without using any Collection or another intermediate Array", was also a sample exercise in my book at school, but what I want to do is get the elements that has duplicates without sorting it.
What I did is I removed the duplicates of arrays first, to get only the unique elements and then I compare it to the original array and count how many times the element has been found. But the problem is it doesn't print the correct elements which has duplicates.
int[] num = {7, 2, 6, 1, 4, 7, 4, 5, 4, 7, 7, 3, 1};
the correct output should be: 7, 1, 4
but instead it outputs: 7, 6, 1
This is my codes:
//method for removing duplicates
public static int[] removeDuplicates(int[] n) {
int limit = n.length;
for(int i = 0; i < limit; i++) {
for(int j = i + 1; j < limit; j++) {
if(n[i] == n[j]) {
for(int k = j; k < limit - 1; k++) {
n[k] = n[k + 1];
}
limit--;
j--;
}
}
}
int[] uniqueValues = new int[limit];
for(int i = 0; i < uniqueValues.length; i++) {
uniqueValues[i] = n[i];
}
return uniqueValues;
}
//method for getting elements that has duplicates
public static int[] getDuplicatedElements(int[] n) {
int[] nCopy = n.clone();
int[] u = removeDuplicates(nCopy);
int count = 0;
int limit = u.length;
for(int i = 0; i < u.length; i++) {
for(int j = 0; j < n.length; j++) {
if(u[i] == n[j]) {
count++;
}
}
if(count == 1) {
for(int k = i; k < limit - 1; k++) {
u[k] = u[k + 1];
}
limit--;
}
count = 0;
}
int[] duplicated = new int[limit];
for(int i = 0; i < duplicated.length; i++) {
duplicated[i] = u[i];
}
return duplicated;
}
//main
public static void main(String[] args) {
int[] num = {7, 2, 6, 1, 4, 7, 4, 5, 4, 7, 7, 3, 1};
//printing original values
System.out.print(Arrays.toString(num));
System.out.println();
int[] a = getDuplicatedElements(num);
System.out.print("Elements with Duplicates: " + Arrays.toString(a));
}
What's the error in my codes here? Please help thanks...
You have two issues:
public static int[] getDuplicatedElements(int[] n) {
int[] nCopy = n.clone();
int[] u = removeDuplicates(nCopy);
System.out.println ("unique " + Arrays.toString (u));
int count = 0;
int limit = u.length;
for(int i = 0; i < limit; i++) { // you must use limit instead of u.length
// in order for the loop to terminate
for(int j = 0; j < n.length; j++) {
if(u[i] == n[j]) {
count++;
}
}
if(count == 1) {
for(int k = i; k < limit - 1; k++) {
u[k] = u[k + 1];
}
limit--;
i--; // you must decrement i after you find a unique element in u
// otherwise you'll be skipping elements in the u array
}
count = 0;
}
int[] duplicated = new int[limit];
for(int i = 0; i < duplicated.length; i++) {
duplicated[i] = u[i];
}
return duplicated;
}
With those fixes, you'll get the expected output:
Elements with Duplicates: [7, 1, 4]
It's fairly simple when using a stream
int[] num = {7, 2, 6, 1, 4, 7, 4, 5, 4, 7, 7, 3, 1};
List<Integer> list = Arrays.stream(num).boxed().collect(Collectors.toList());
list.stream().filter(i -> Collections.frequency(list, i) > 1)
.collect(Collectors.toSet()).forEach(System.out::println);

Fast way to declare incremental elements of array - Java

Say I have 10 integer variables, x1 to x10.
I have an integer array, as follows:
Int[] countup = new Int[10];
I would like to specify the elements of the array as follows:
countup[0] = x1;
countup[1] = x1 + x2;
countup[2] = x1 + x2 + x3;
And so on until countup[9] is the sum of x1 to x10.
I could do this manually if it was just 10 elements, but in the actual program I'm writing, there's over 100 elements of the array. Is there any way to set the variables of this array quickly?
A for loop is your best bet, simply put your 10 (or 100) integers into an array of it's own, then loop over your second array referencing indexes of the first array:
int[] xNumbers = { x1, x2, x3, ... x10 };
int[] countup = new int[10];
//Set the 0 index so we don't have to do extra check inside the for loop
//for out-of-bounds exception
countup[0] = xNumbers[0];
for (int i = 1; i < 10; i++) {
//countup[i-1] is why we set index 0 outside of the loop
countup[i] = xNumbers[i] + countup[i-1];
}
since countup[i-1] is the sum of the previous numbers, the previous additions are already done for you. In case you don't know what a for loop is, more information can be found here
Succinctly:
int[] xNums = { /*your x numbers here*/ };
int[] resultArray = new int[xNums.length];
for(int n = 0; n < xNums.length; n++)
{
for(int i = 0; i <= n; i++)
{
resultArray[n]+=xNums[i];
}
}
Hope that makes sense!
I wanted to find a way to do it in Java 8, and the other answer is probably better:
Here's what I have, but it seems redundant and a waste of time, but I'm unfamiliar with Java 8:
public static void main(String[] args) {
int[] arr = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int length = arr.length;
for (int i = 1; i < length; i++) {
System.out.println(Arrays.toString(Arrays.copyOfRange(arr, 0, i + 1)));
arr[i] = Arrays.stream(Arrays.copyOfRange(arr, 0, i + 1)).sum();
}
System.out.println(Arrays.toString(arr));
}
arr[9] is [1, 3, 7, 15, 31, 63, 127, 255, 511, 1023]
I believe I also interpreted the question differently. I think he wanted in index[i] the sum of all previous elements.
If my interpretation of your question is correct, to do it without Java 8, using 2 loops:
int[] array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int length = array.length;
for(int i = 1; i < length; i++) {
int sumSoFar = 0;
for(int j = 0; j <= i; j ++) {
sumSoFar += array[j];
}
array[i] = sumSoFar;
}

How to remove duplicates from a list using an auxiliary array in Java?

I am trying to remove duplicates from a list by creating a temporary array that stores the indices of where the duplicates are, and then copies off the original array into another temporary array while comparing the indices to the indices I have stored in my first temporary array.
public void removeDuplicates()
{
double tempa [] = new double [items.length];
int counter = 0;
for ( int i = 0; i< numItems ; i++)
{
for(int j = i + 1; j < numItems; j++)
{
if(items[i] ==items[j])
{
tempa[counter] = j;
counter++;
}
}
}
double tempb [] = new double [ items.length];
int counter2 = 0;
int j =0;
for(int i = 0; i < numItems; i++)
{
if(i != tempa[j])
{
tempb[counter2] = items[i];
counter2++;
}
else
{
j++;
}
}
items = tempb;
numItems = counter2;
}
and while the logic seems right, my compiler is giving me an arrayindexoutofbounds error at
tempa[counter] = j;
I don't understand how counter could grow to above the value of items.length, where is the logic flaw?
You are making things quite difficult for yourself. Let Java do the heavy lifting for you. For example LinkedHashSet gives you uniqueness and retains insertion order. It will also be more efficient than comparing every value with every other value.
double [] input = {1,2,3,3,4,4};
Set<Double> tmp = new LinkedHashSet<Double>();
for (Double each : input) {
tmp.add(each);
}
double [] output = new double[tmp.size()];
int i = 0;
for (Double each : tmp) {
output[i++] = each;
}
System.out.println(Arrays.toString(output));
Done for int arrays, but easily coud be converted to double.
1) If you do not care about initial array elements order:
private static int[] withoutDuplicates(int[] a) {
Arrays.sort(a);
int hi = a.length - 1;
int[] result = new int[a.length];
int j = 0;
for (int i = 0; i < hi; i++) {
if (a[i] == a[i+1]) {
continue;
}
result[j] = a[i];
j++;
}
result[j++] = a[hi];
return Arrays.copyOf(result, j);
}
2) if you care about initial array elements order:
private static int[] withoutDuplicates2(int[] a) {
HashSet<Integer> keys = new HashSet<Integer>();
int[] result = new int[a.length];
int j = 0;
for (int i = 0 ; i < a.length; i++) {
if (keys.add(a[i])) {
result[j] = a[i];
j++;
}
}
return Arrays.copyOf(result, j);
}
3) If you do not care about initial array elements order:
private static Object[] withoutDuplicates3(int[] a) {
HashSet<Integer> keys = new HashSet<Integer>();
for (int value : a) {
keys.add(value);
}
return keys.toArray();
}
Imagine this was your input data:
Index: 0, 1, 2, 3, 4, 5, 6, 7, 8
Value: 1, 2, 3, 3, 3, 3, 3, 3, 3
Then according to your algorithm, tempa would need to be:
Index: 0, 1, 2, 3, 4, 5, 6, 7, 8, ....Exception!!!
Value: 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 5, 6, 7, 8, 6, 7, 8, 7, 8, 8
Why do you have this problem? Because the first set of nested for loops does nothing to prevent you from trying to insert duplicates of the duplicate array indices!
What is the best solution?
Use a Set!
Sets guarantee that there are no duplicate entries in them. If you create a new Set and then add all of your array items to it, the Set will prune the duplicates. Then it is just a matter of going back from the Set to an array.
Alternatively, here is a very C-way of doing the same thing:
//duplicates will be a truth table indicating which indices are duplicates.
//initially all values are set to false
boolean duplicates[] = new boolean[items.length];
for ( int i = 0; i< numItems ; i++) {
if (!duplicates[i]) { //if i is not a known duplicate
for(int j = i + 1; j < numItems; j++) {
if(items[i] ==items[j]) {
duplicates[j] = true; //mark j as a known duplicate
}
}
}
}
I leave it to you to figure out how to finish.
import java.util.HashSet;
import sun.security.util.Length;
public class arrayduplication {
public static void main(String[] args) {
int arr[]={1,5,1,2,5,2,10};
TreeSet< Integer>set=new TreeSet<Integer>();
for(int i=0;i<arr.length;i++){
set.add(Integer.valueOf(arr[i]));
}
System.out.println(set);
}
}
You have already used num_items to bound your loop. Use that variable to set your array size for tempa also.
double tempa [] = new double [num_items];
Instead of doing it in array, you can simply use java.util.Set.
Here an example:
public static void main(String[] args)
{
Double[] values = new Double[]{ 1.0, 2.0, 2.0, 2.0, 3.0, 10.0, 10.0 };
Set<Double> singleValues = new HashSet<Double>();
for (Double value : values)
{
singleValues.add(value);
}
System.out.println("singleValues: "+singleValues);
// now convert it into double array
Double[] dValues = singleValues.toArray(new Double[]{});
}
Here's another alternative without the use of sets, only primitive types:
public static double [] removeDuplicates(double arr[]) {
double [] tempa = new double[arr.length];
int uniqueCount = 0;
for (int i=0;i<arr.length;i++) {
boolean unique = true;
for (int j=0;j<uniqueCount && unique;j++) {
if (arr[i] == tempa[j]) {
unique = false;
}
}
if (unique) {
tempa[uniqueCount++] = arr[i];
}
}
return Arrays.copyOf(tempa, uniqueCount);
}
It does require a temporary array of double objects on the way towards getting your actual result.
You can use a set for removing multiples.

Categories

Resources