How can we access to a multidimensional array - java

How can we access to a multiple dimension array without even knowing it !
For example :
Object[][] inputs = { new Object[] { "a", "ab", "abc" },
new Object[] { "abc", "ab", "a" },
new Object[] { "big", new Object[] { "ab", "a", }, "t" },
new Object[] { "big", new Object[] { "ab", "a", new Object[] { "superbig", "a" } }, "tiny" },
new Object[] { 123, 23123123, "a" },
new Object[] { null, new Object[] {}, "a" } };
I thought it was 2 dimensional but it's not 2 (which i'm not happy with that syntax of java) and i need to get all the information of the inputs array object.
How am i suppose to solve this ? Is there any method for transforming a multidimensional array into one dimension ?
P.S.: The Output should be { abc, abc, big,superbig,23123123,a} (it's the biggest string of each line of the object !)

You can easily flatten any-dimensional array to single dimension, at runtime, using reflection. You can use it to compute find longest strings as you required with your edit.
Working runnable example program:
import java.lang.reflect.*;
import java.util.*;
public class Program {
private static Object[] toSingleDimension(Object array) {
ArrayList<Object> arrayList = new ArrayList<>();
toSingleDimensionRecursive(arrayList, array);
return arrayList.toArray();
}
private static void toSingleDimensionRecursive(ArrayList<Object> output, Object object) {
if (object == null) {
output.add(null);
} else if (!object.getClass().isArray()) {
output.add(object);
} else {
int length = Array.getLength(object);
for (int i = 0; i < length; ++i) {
Object value = Array.get(object, i);
toSingleDimensionRecursive(output, value);
}
}
}
private static String findLongestString(Object[] array) {
if (array == null) {
return null;
}
String result = null;
for (Object object : array) {
if (object != null) {
String text = object.toString();
if (result == null) {
result = text;
} else if (text != null && text.length() > result.length()) {
result = text;
}
}
}
return result;
}
public static void main(String[] args) {
Object[][] inputs = {new Object[]{"a", "ab", "abc"},
new Object[]{"abc", "ab", "a"},
new Object[]{"big", new Object[]{"ab", "a",}, "t"},
new Object[]{"big", new Object[]{"ab", "a", new Object[]{"superbig", "a"}}, "tiny"},
new Object[]{123, 23123123, "a"},
new Object[]{null, new Object[]{}, "a"}};
// Object[] data = toSingleDimension(inputs);
// System.out.println(Arrays.asList(data));
ArrayList<String> longestStrings = new ArrayList<>();
for (Object input : inputs) {
Object[] array = toSingleDimension(input);
String longest = findLongestString(array);
if (longest != null) {
longestStrings.add(longest);
}
}
System.out.println("Longest strings of arrays: " + longestStrings);
}
}
Outputs:
Longest strings of arrays: [abc, abc, big, superbig, 23123123, a]

You can use recursion to achieve this easily.
public List<Object> convert(Object input) {
List<Object> objectList = new ArrayList<>();
if (input instanceof Object[]) {
for (Object object : (Object[]) input) {
objectList.addAll(convert(object)); // Instead of addAll here, just add max element. I am a little too lazy to implement that...:)
}
} else {
objectList.add(input);
}
return objectList;
}

Related

Java pairing names from array

So I am trying to create small Java program where names from array are paired. But I don't know how to proceed. I have array with names and the object is to pair two names randomly to make a team. There should be some statement so certain pairs couldn't be made: Miller & James can't be in the same team and no dublicates. How do I do this?
Example output:
James & Hal
import java.util.Random;
public class Teams {
public static void main (String [] args) {
String [] arr = {"John", "James", "George", "Miller", "Hal", "Dan"};
Random random = new Random();
int select = random.nextInt(arr.length);
int selectSecond = random.nextInt(arr.length);
System.out.println(arr[select]);
System.out.println(arr[selectSecond]);
}
}
You can delete the first chosen name from the array and then choose again to get the second one. To delete an element from an array see Removing an element from an Array (Java). Here is one possible implementation (but I didn't test it):
public static void main (String [] args) {
String [] arr = {"John", "James", "George", "Miller", "Hal", "Dan"};
Random random = new Random();
int select = random.nextInt(arr.length);
arr = removeElements(arr, arr[select]);
int selectSecond = random.nextInt(arr.length);
System.out.println(arr[select]);
System.out.println(arr[selectSecond]);
}
// import java.util.LinkedList;
public static String[] removeElements(String[] input, String deleteMe) {
List result = new LinkedList();
for(String item : input)
if(!deleteMe.equals(item))
result.add(item);
return (String[]) result.toArray(input);
}
I would like to use Collections.shuffle instead, and a do while loop like so :
String[] arr = {"John", "James", "George", "Miller", "Hal", "Dan"};
List<String> list = Arrays.asList(arr);
String name1, name2;
do {
Collections.shuffle(list);
name1 = list.get(0);
name2 = list.get(1);
} while ((name2.equals("Miller") && name1.equals("James"))
|| (name1.equals("James") && name2.equals("Miller")));
System.out.println(String.format("%s & %s", name1, name2));
With this solution you don't need to check if the both names are same or not, you just need to check if the two name not equals in the same pair to Miller and James
It will depend which perspective you want to attack here. If you just want to "do the job", you have an extensive list of possibilities (as we already have here), but I would just take care with readability:
public class Teams {
private static String[][] teamsToAvoid = {{"James", "Miller"}, {"John", "Hal"}};
private static String[][] teamsFormed = new String[3][2];
public static void main(String[] args){
String[] names = {"John", "James", "George", "Miller", "Hal", "Dan"};
List<String> namesList = new ArrayList<>(Arrays.asList(names));
Collections.shuffle(namesList);
do {
formTeam(namesList, 0, 1);
} while(namesList != null && !namesList.isEmpty());
for(String[] team : teamsFormed){
System.out.println("Team: {" + team[0] + ", " + team[1] + "}");
}
}
private static void formTeam(List<String> namesList, int firstPlayerIndex, int secondPlayerIndex) {
if(isTeamPossible(namesList.get(firstPlayerIndex), namesList.get(secondPlayerIndex))){
String firstPlayer = namesList.get(firstPlayerIndex);
String secondPlayer = namesList.get(secondPlayerIndex);
teamsFormed[getFormedTeamNextIndex()] = new String[]{firstPlayer, secondPlayer};
namesList.remove(namesList.indexOf(firstPlayer));
namesList.remove(namesList.indexOf(secondPlayer));
} else {
formTeam(namesList, firstPlayerIndex, ++secondPlayerIndex);
}
}
private static boolean isTeamPossible(String player1, String player2) {
for(String[] teamToAvoid : teamsToAvoid){
if(Arrays.asList(teamToAvoid).contains(player1) && Arrays.asList(teamToAvoid).contains(player2)){
return false;
}
}
return true;
}
private static int getFormedTeamNextIndex() {
for(int i = 0; i < teamsFormed.length; i++){
if(teamsFormed[i][0] == null && teamsFormed[i][1] == null)
return i;
}
return 0;
}
}
Doing this you will prevent the same pair in different order and remove those players from the list (preventing their reuse).
I would pay attention when removing from list directly by index also, because when you remove one item the index for items after that one change.

How to deal with multiplicity when checking if an arraylist is a subset

I have two Arraylist and I want to check if one is a subset of the other (ordering is not important in the comparison).
The problem is: Lets say Ar1={e,e,r} and Ar2={e,r,b,d}. In my code it says Ar1 is a subset. But I want it to say false, cause Ar2 has only one e. How to do that?
public static void dostuff(String word1,String word2){
List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList<String>();
for (String character : word1.split("")) {
list1.add(character);
}
for (String character : word2.split("")) {
list2.add(character);
}
boolean sub = list1.containsAll(list2) || list2.containsAll(list1);
System.out.println(sub);
}
I think this may be what you want. Note that list2.remove(elem) returns true if an element was removed, and false if not.
public static boolean dostuff(String word1,String word2){
List<String> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
List<String> list3;
for (String character : word1.split("")) {
list1.add(character);
}
for (String character : word2.split("")) {
list2.add(character);
}
list3 = new ArrayList<>(list2);
boolean isSubset = true;
for (final String elem : list1) {
if (!list2.remove(elem)) {
isSubset = false;
break;
}
}
if (isSubset) {
return true;
}
for (final String elem : list3) {
if (!list1.remove(elem)) {
return false;
}
}
return true;
}
#Johdoe. The below logic may help you. you can optimize if you want.
ArrayList<String> list1 = new ArrayList<String>();
ArrayList<String> list2 = new ArrayList<String>();
list1.add("e");
list1.add("a");
list1.add("r");
list2.add("e");
list2.add("r");
list2.add("b");
list2.add("d");
list2.add("a");
System.out.println("list2 " + list2);
System.out.println("list1 " + list1);
Set<Integer> tempList = new HashSet<Integer>();
System.out.println(" containsAll " + list2.containsAll(list1));
for (int i = 0; i < list2.size(); i++) {
for (int j = 0; j < list1.size(); j++) {
if (list2.get(i).equals(list1.get(j))) {
tempList.add(i);
}
}
}
System.out.println(" tempList " + tempList);
System.out.println("list 1 is subset of list 2 "
+ (tempList.size() == list1.size()));
Note also that a mathematical, and java, set is unique, so be careful of using the term "subset".
You can use a frequency map to test if one list "has each element in another list, with the same or fewer occurrences". i.e. once you have your list you can convert it into a Map<T, Integer> to store the counts of each list element. The use of a map avoids mutating the original lists (which you would do if testing by removing elements from the master list as you encounter them):
public static <T> boolean isSublist(List<T> masterList, List<T> subList) {
Map<T, Integer> masterMap = new HashMap<T, Integer>();
for (T t : masterList) masterMap.put(t, 1 + masterMap.getOrDefault(t, 0));
Map<T, Integer> testMap = new HashMap<T, Integer>();
for (T t : subList) testMap.put(t, 1 + testMap.getOrDefault(t, 0));
for(Map.Entry<T, Integer> entry : testMap.entrySet()) {
if (masterMap.getOrDefault(entry.getKey(), 0) < entry.getValue()) return false;
}
return true;
}
getOrDefault is only available as of Java 8, but you can easily write your own method to take care of the same operation.
I have found a solution myself, please check of this is right, but i believe it is.
public static void dostuff(String word1, String word2) {
boolean sub = false;
ArrayList<String> list1 = new ArrayList<String>();
ArrayList<String> list2 = new ArrayList<String>();
ArrayList<String> list3 = new ArrayList<String>();
for (int i = 0; i < word1.length(); i++) {
list1.add(word1.split("")[i]);
}
for (int i = 0; i < word2.length(); i++) {
list2.add(word2.split("")[i]);
}
if (list1.size() >= list2.size()) {
for (String i : list2) {
if (list1.contains(i)) {
list1.remove(i);
list3.add(i);
}
}
if (list2.containsAll(list3) && list2.size() == list3.size()) {
sub = true;
}
} else if (list2.size() > list1.size()) {
for (String i : list1) {
if (list2.contains(i)) {
list2.remove(i);
list3.add(i);
}
if (list1.containsAll(list3) && list1.size() == list3.size()) {
sub = true;
}
}
}
System.out.println(sub);
}
You could use a couple of maps to store the frequency of each letter:
public static void dostuff(String word1, String word2) {
Map<String, Long> freq1 = Arrays.stream(word1.split("")).collect(
Collectors.groupingBy(Function.identity(), Collectors.counting()));
Map<String, Long> freq2 = Arrays.stream(word2.split("")).collect(
Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println(contains(freq1, freq2) || contains(freq2, freq1));
}
Where the contains method would be as follows:
private static boolean contains(Map<String, Long> freq1, Map<String, Long> freq2) {
return freq1.entrySet().stream().allMatch(
e1 -> e1.getValue().equals(freq2.get(e1.getKey())));
}
Test:
dostuff("eer", "erbd"); // {r=1, e=2}, {b=1, r=1, d=1, e=1}, false
dostuff("erbed", "eer"); // {b=1, r=1, d=1, e=2}, {r=1, e=2}, true
The idea is to use java 8 streams to create the frequencies map, and then, stream the entry set of both maps to compare all the elements and their frequencies. If all entries match, then it means that the second list contains all the elements of the first list with the same frequencies, regardless of the order.
In case the result is false for the first list, the check is performed the other way round as well, as per the question requirements.
Now that I understand that the order of the contents doesn't matter, you just want to know if all the characters of one string exists in another (with the same frequency) or vice versa.
Try this function, it'll check everything without having to call the method twice and without using streams:
public static boolean subsetExists(String s1, String s2) {
String temp = s2.replaceAll(String.format("[^%s]", s1), "");
char[] arr1 = s1.toCharArray();
char[] arr2 = temp.toCharArray();
Arrays.sort(arr1);
Arrays.sort(arr2);
boolean isSubset = new String(arr2).contains(new String(arr1));
if (!isSubset) {
temp = s1.replaceAll(String.format("[^%s]", s2), "");
arr1 = temp.toCharArray();
arr2 = s2.toCharArray();
Arrays.sort(arr1);
Arrays.sort(arr2);
isSubset = new String(arr1).contains(new String(arr2));
}
return isSubset;
}
You don't have to bother turning your Strings into Lists. What's happening is we're checking if all the letters in s1 exist in s2 or vice versa.
We removed characters that are not in s1 from s2 and stored that result in a temporary String. Converted both the temporary String and s1 into char[]s. We then sort both arrays and convert them back into Strings. We then can check if NEW SORTED temporary String contains() the NEW SORTED s1. If this result is false, then we apply the same logical check from s2 to s1.
Usage:
public static void main(String[] args) throws Exception {
String s1 = "eer";
String s2 = "bderz";
String s3 = "bderzzeee";
System.out.println(subsetExists(s1, s2));
System.out.println(subsetExists(s1, s3));
}
public static boolean subsetExists(String s1, String s2) {
String temp = s2.replaceAll(String.format("[^%s]", s1), "");
char[] arr1 = s1.toCharArray();
char[] arr2 = temp.toCharArray();
Arrays.sort(arr1);
Arrays.sort(arr2);
boolean isSubset = new String(arr2).contains(new String(arr1));
if (!isSubset) {
temp = s1.replaceAll(String.format("[^%s]", s2), "");
arr1 = temp.toCharArray();
arr2 = s2.toCharArray();
Arrays.sort(arr1);
Arrays.sort(arr2);
isSubset = new String(arr1).contains(new String(arr2));
}
return isSubset;
}
Results:
false
true
Here is a Working Solution
Check Demo
public static void main (String[] args) throws java.lang.Exception
{
dostuff("eer","erbd");
}
public static void dostuff(String word1, String word2) {
List<String> list1 = new ArrayList<String>();
for (String character : word1.split("")) {
list1.add(character);
}
boolean sub = true;
for (String character : word2.split("")) {
if (list1.remove(character)) {
if (list1.isEmpty()) {
break;
}
} else {
sub = false;
break;
}
}
System.out.println(sub);
}

Converting Lists of Lists into String array

I want to convert lists of lists into two separate string arrays.
I want to convert taglist into string array TagArray[] and tokenlist into array called TokenArray.
I tried many ways but there are many ways to convert Converting an ArrayList into a 2D Array but I cannot find any method to convert Lists of lists to String array. Can anyone help me to do this.
taglist
[[NON, NON], [NON, NON ], [NON, NON, NON], [NON, NON] ,[ENTITY, ENTITY]]
tokenlist
[[John, ran], [John, jumped], [The, dog, jumped], [Mary, sat], [Finland, India]]
I tried the following way
for(int i=0;i<tokenlist.size();i++)
{
String[] words = tokenlist.get(i);
}
I am getting the output when i use above way. but the problem is that i have to take i th value from tokenlist and taglist at the same time
OR
I have to convert this into 3 D array which has the following format
static final String[][][] WORDS_TAGS = new String[][][]
{
{ { "John", "ran" }, { "NON", "NON" } },
{ { "John", "jumped"}, { "NON", "NON "} },
{ { "The", "dog", "jumped"}, { "NON", "NON", "NON" } },
{ { "Mary", "sat"}, { "NON", "NON"} },
{ { "Finland","India" }, { "ENTITY","ENTITY" } },
};
try this
List<List<String>> l1 = Arrays.asList(Arrays.asList("NON", "NON"),
Arrays.asList("NON", "NON"),
Arrays.asList("NON", "NON", "NON"),
Arrays.asList("NON", "NON"), Arrays.asList("ENTITY", "ENTITY"));
List<List<String>> l2 = Arrays
.asList(Arrays.asList("John", "ran"),
Arrays.asList("John", "jumped"),
Arrays.asList("The", "dog", "jumped"),
Arrays.asList("Mary", "sat"),
Arrays.asList("Finland", "India"));
String[][][] a = new String[l1.size()][][];
for (int i = 0; i < l1.size(); i++) {
a[i] = new String[][] {
l2.get(i).toArray(new String[l2.get(i).size()]),
l1.get(i).toArray(new String[l1.get(i).size()]) };
}
System.out.println(Arrays.deepToString(a));
output
[[[John, ran], [NON, NON]], [[John, jumped], [NON, NON]], [[The, dog, jumped], [NON, NON, NON]], [[Mary, sat], [NON, NON]], [[Finland, India], [ENTITY, ENTITY]]]
String[] words = new String[20];
int index = 0;
for(int i=0;i<L2.size();i++)
{
List l5 = (List)L2.get(i);
for(int j=0;j<l5.size();j++){
words[index] = (String)l5.get(j);
index++;
}
}
you need two for loop. one for external and another for internal
Try this
String[][][] newArray = new String[taglist.size()][2][];
for(int i=0;i<taglist.size();i++){
String[] arr=tokenlist.get(i).toArray(new String[tokenlist.get(i).size()]);
newArray[i][0]= arr;
arr= taglist.get(i).toArray(new String[taglist.get(i).size()]);
newArray[i][1]= arr;
}

Each Array with each [duplicate]

I have an 2D-array like this in java
transmission communication tv television
approach memorycode
methodact
I need to get all combinations like:
{transmission,approach,methodact},{transmission,memorycode,methodact},{communication,approach,methodact},...
Can someone provide an example that will work for nXn arrays, even if it has only two rows?
This should do the trick:
static Set<List<String>> allComb(String[][] opts) {
Set<List<String>> results = new HashSet<List<String>>();
if (opts.length == 1) {
for (String s : opts[0])
results.add(new ArrayList<String>(Arrays.asList(s)));
} else
for (String str : opts[0]) {
String[][] tail = Arrays.copyOfRange(opts, 1, opts.length);
for (List<String> combs : allComb(tail)) {
combs.add(str);
results.add(combs);
}
}
return results;
}
This code in JavaScript can help you:
var sampleArray = [["transmission","communication","tv","television"], ["approach","memorycode"], ["methodact"]];
var GetAllCombinations = function(array2d)
{
var ret=[];
var fn = function(arr,index,cur)
{
var ret = [];
for (var i=0; i<arr[index].length; i++)
{
var x = cur.slice(0);
x.push(arr[index][i]);
if (index == arr.length-1)
ret.push(x);
else
ret = ret.concat(fn(arr,index+1,x));
}
return ret;
};
return fn(array2d,0,[]);
}
console.log(GetAllCombinations(sampleArray));
It builds all combinations starting with a given array, iterates over all the options for that level and call it recursively, then concatenate it with the result.

Remove Null Value from String array in java

How to remove null value from String array in java?
String[] firstArray = {"test1","","test2","test4",""};
I need the "firstArray" without null ( empty) values like this
String[] firstArray = {"test1","test2","test4"};
If you want to avoid fencepost errors and avoid moving and deleting items in an array, here is a somewhat verbose solution that uses List:
import java.util.ArrayList;
import java.util.List;
public class RemoveNullValue {
public static void main( String args[] ) {
String[] firstArray = {"test1", "", "test2", "test4", "", null};
List<String> list = new ArrayList<String>();
for(String s : firstArray) {
if(s != null && s.length() > 0) {
list.add(s);
}
}
firstArray = list.toArray(new String[list.size()]);
}
}
Added null to show the difference between an empty String instance ("") and null.
Since this answer is around 4.5 years old, I'm adding a Java 8 example:
import java.util.Arrays;
import java.util.stream.Collectors;
public class RemoveNullValue {
public static void main( String args[] ) {
String[] firstArray = {"test1", "", "test2", "test4", "", null};
firstArray = Arrays.stream(firstArray)
.filter(s -> (s != null && s.length() > 0))
.toArray(String[]::new);
}
}
It seems no one has mentioned about using nonNull method which also can be used with streams in Java 8 to remove null (but not empty) as:
String[] origArray = {"Apple", "", "Cat", "Dog", "", null};
String[] cleanedArray = Arrays.stream(firstArray).filter(Objects::nonNull).toArray(String[]::new);
System.out.println(Arrays.toString(origArray));
System.out.println(Arrays.toString(cleanedArray));
And the output is:
[Apple, , Cat, Dog, , null]
[Apple, , Cat, Dog, ]
If we want to incorporate empty also then we can define a utility method (in class Utils(say)):
public static boolean isEmpty(String string) {
return (string != null && string.isEmpty());
}
And then use it to filter the items as:
Arrays.stream(firstArray).filter(Utils::isEmpty).toArray(String[]::new);
I believe Apache common also provides a utility method StringUtils.isNotEmpty which can also be used.
If you actually want to add/remove items from an array, may I suggest a List instead?
String[] firstArray = {"test1","","test2","test4",""};
ArrayList<String> list = new ArrayList<String>();
for (String s : firstArray)
if (!s.equals(""))
list.add(s);
Then, if you really need to put that back into an array:
firstArray = list.toArray(new String[list.size()]);
Using Google's guava library
String[] firstArray = {"test1","","test2","test4","",null};
Iterable<String> st=Iterables.filter(Arrays.asList(firstArray),new Predicate<String>() {
#Override
public boolean apply(String arg0) {
if(arg0==null) //avoid null strings
return false;
if(arg0.length()==0) //avoid empty strings
return false;
return true; // else true
}
});
This is the code that I use to remove null values from an array which does not use array lists.
String[] array = {"abc", "def", null, "g", null}; // Your array
String[] refinedArray = new String[array.length]; // A temporary placeholder array
int count = -1;
for(String s : array) {
if(s != null) { // Skips over null values. Add "|| "".equals(s)" if you want to exclude empty strings
refinedArray[++count] = s; // Increments count and sets a value in the refined array
}
}
// Returns an array with the same data but refits it to a new length
array = Arrays.copyOf(refinedArray, count + 1);
Quite similar approve as already posted above. However it's easier to read.
/**
* Remove all empty spaces from array a string array
* #param arr array
* #return array without ""
*/
public static String[] removeAllEmpty(String[] arr) {
if (arr == null)
return arr;
String[] result = new String[arr.length];
int amountOfValidStrings = 0;
for (int i = 0; i < arr.length; i++) {
if (!arr[i].equals(""))
result[amountOfValidStrings++] = arr[i];
}
result = Arrays.copyOf(result, amountOfValidStrings);
return result;
}
A gc-friendly piece of code:
public static<X> X[] arrayOfNotNull(X[] array) {
for (int p=0, N=array.length; p<N; ++p) {
if (array[p] == null) {
int m=p; for (int i=p+1; i<N; ++i) if (array[i]!=null) ++m;
X[] res = Arrays.copyOf(array, m);
for (int i=p+1; i<N; ++i) if (array[i]!=null) res[p++] = array[i];
return res;
}
}
return array;
}
It returns the original array if it contains no nulls. It does not modify the original array.
Those are zero-length strings, not null. But if you want to remove them:
firstArray[0] refers to the first element
firstArray[1] refers to the second element
You can move the second into the first thusly:
firstArray[0] = firstArray[1]
If you were to do this for elements [1,2], then [2,3], etc. you would eventually shift the entire contents of the array to the left, eliminating element 0. Can you see how that would apply?

Categories