Related
Given an array of n Objects, let's say it is an array of strings, and it has the following values:
foo[0] = "a";
foo[1] = "cc";
foo[2] = "a";
foo[3] = "dd";
What do I have to do to delete/remove all the strings/objects equal to "a" in the array?
[If you want some ready-to-use code, please scroll to my "Edit3" (after the cut). The rest is here for posterity.]
To flesh out Dustman's idea:
List<String> list = new ArrayList<String>(Arrays.asList(array));
list.removeAll(Arrays.asList("a"));
array = list.toArray(array);
Edit: I'm now using Arrays.asList instead of Collections.singleton: singleton is limited to one entry, whereas the asList approach allows you to add other strings to filter out later: Arrays.asList("a", "b", "c").
Edit2: The above approach retains the same array (so the array is still the same length); the element after the last is set to null. If you want a new array sized exactly as required, use this instead:
array = list.toArray(new String[0]);
Edit3: If you use this code on a frequent basis in the same class, you may wish to consider adding this to your class:
private static final String[] EMPTY_STRING_ARRAY = new String[0];
Then the function becomes:
List<String> list = new ArrayList<>();
Collections.addAll(list, array);
list.removeAll(Arrays.asList("a"));
array = list.toArray(EMPTY_STRING_ARRAY);
This will then stop littering your heap with useless empty string arrays that would otherwise be newed each time your function is called.
cynicalman's suggestion (see comments) will also help with the heap littering, and for fairness I should mention it:
array = list.toArray(new String[list.size()]);
I prefer my approach, because it may be easier to get the explicit size wrong (e.g., calling size() on the wrong list).
An alternative in Java 8:
String[] filteredArray = Arrays.stream(array)
.filter(e -> !e.equals(foo)).toArray(String[]::new);
Make a List out of the array with Arrays.asList(), and call remove() on all the appropriate elements. Then call toArray() on the 'List' to make back into an array again.
Not terribly performant, but if you encapsulate it properly, you can always do something quicker later on.
You can always do:
int i, j;
for (i = j = 0; j < foo.length; ++j)
if (!"a".equals(foo[j])) foo[i++] = foo[j];
foo = Arrays.copyOf(foo, i);
You can use external library:
org.apache.commons.lang.ArrayUtils.remove(java.lang.Object[] array, int index)
It is in project Apache Commons Lang http://commons.apache.org/lang/
See code below
ArrayList<String> a = new ArrayList<>(Arrays.asList(strings));
a.remove(i);
strings = new String[a.size()];
a.toArray(strings);
If you need to remove multiple elements from array without converting it to List nor creating additional array, you may do it in O(n) not dependent on count of items to remove.
Here, a is initial array, int... r are distinct ordered indices (positions) of elements to remove:
public int removeItems(Object[] a, int... r) {
int shift = 0;
for (int i = 0; i < a.length; i++) {
if (shift < r.length && i == r[shift]) // i-th item needs to be removed
shift++; // increment `shift`
else
a[i - shift] = a[i]; // move i-th item `shift` positions left
}
for (int i = a.length - shift; i < a.length; i++)
a[i] = null; // replace remaining items by nulls
return a.length - shift; // return new "length"
}
Small testing:
String[] a = {"0", "1", "2", "3", "4"};
removeItems(a, 0, 3, 4); // remove 0-th, 3-rd and 4-th items
System.out.println(Arrays.asList(a)); // [1, 2, null, null, null]
In your task, you can first scan array to collect positions of "a", then call removeItems().
There are a lot of answers here--the problem as I see it is that you didn't say WHY you are using an array instead of a collection, so let me suggest a couple reasons and which solutions would apply (Most of the solutions have already been answered in other questions here, so I won't go into too much detail):
reason: You didn't know the collection package existed or didn't trust it
solution: Use a collection.
If you plan on adding/deleting from the middle, use a LinkedList. If you are really worried about size or often index right into the middle of the collection use an ArrayList. Both of these should have delete operations.
reason: You are concerned about size or want control over memory allocation
solution: Use an ArrayList with a specific initial size.
An ArrayList is simply an array that can expand itself, but it doesn't always need to do so. It will be very smart about adding/removing items, but again if you are inserting/removing a LOT from the middle, use a LinkedList.
reason: You have an array coming in and an array going out--so you want to operate on an array
solution: Convert it to an ArrayList, delete the item and convert it back
reason: You think you can write better code if you do it yourself
solution: you can't, use an Array or Linked list.
reason: this is a class assignment and you are not allowed or you do not have access to the collection apis for some reason
assumption: You need the new array to be the correct "size"
solution:
Scan the array for matching items and count them. Create a new array of the correct size (original size - number of matches). use System.arraycopy repeatedly to copy each group of items you wish to retain into your new Array. If this is a class assignment and you can't use System.arraycopy, just copy them one at a time by hand in a loop but don't ever do this in production code because it's much slower. (These solutions are both detailed in other answers)
reason: you need to run bare metal
assumption: you MUST not allocate space unnecessarily or take too long
assumption: You are tracking the size used in the array (length) separately because otherwise you'd have to reallocate your array for deletes/inserts.
An example of why you might want to do this: a single array of primitives (Let's say int values) is taking a significant chunk of your ram--like 50%! An ArrayList would force these into a list of pointers to Integer objects which would use a few times that amount of memory.
solution: Iterate over your array and whenever you find an element to remove (let's call it element n), use System.arraycopy to copy the tail of the array over the "deleted" element (Source and Destination are same array)--it is smart enough to do the copy in the correct direction so the memory doesn't overwrite itself:
System.arraycopy(ary, n+1, ary, n, length-n)
length--;
You'll probably want to be smarter than this if you are deleting more than one element at a time. You would only move the area between one "match" and the next rather than the entire tail and as always, avoid moving any chunk twice.
In this last case, you absolutely must do the work yourself, and using System.arraycopy is really the only way to do it since it's going to choose the best possibly way to move memory for your computer architecture--it should be many times faster than any code you could reasonably write yourself.
Something about the make a list of it then remove then back to an array strikes me as wrong. Haven't tested, but I think the following will perform better. Yes I'm probably unduly pre-optimizing.
boolean [] deleteItem = new boolean[arr.length];
int size=0;
for(int i=0;i<arr.length;i==){
if(arr[i].equals("a")){
deleteItem[i]=true;
}
else{
deleteItem[i]=false;
size++;
}
}
String[] newArr=new String[size];
int index=0;
for(int i=0;i<arr.length;i++){
if(!deleteItem[i]){
newArr[index++]=arr[i];
}
}
I realise this is a very old post, but some of the answers here helped me out, so here's my tuppence' ha'penny's worth!
I struggled getting this to work for quite a while before before twigging that the array that I'm writing back into needed to be resized, unless the changes made to the ArrayList leave the list size unchanged.
If the ArrayList that you're modifying ends up with greater or fewer elements than it started with, the line List.toArray() will cause an exception, so you need something like List.toArray(new String[] {}) or List.toArray(new String[0]) in order to create an array with the new (correct) size.
Sounds obvious now that I know it. Not so obvious to an Android/Java newbie who's getting to grips with new and unfamiliar code constructs and not obvious from some of the earlier posts here, so just wanted to make this point really clear for anybody else scratching their heads for hours like I was!
Initial array
int[] array = {5,6,51,4,3,2};
if you want remove 51 that is index 2, use following
for(int i = 2; i < array.length -1; i++){
array[i] = array[i + 1];
}
EDIT:
The point with the nulls in the array has been cleared. Sorry for my comments.
Original:
Ehm... the line
array = list.toArray(array);
replaces all gaps in the array where the removed element has been with null. This might be dangerous, because the elements are removed, but the length of the array remains the same!
If you want to avoid this, use a new Array as parameter for toArray(). If you don`t want to use removeAll, a Set would be an alternative:
String[] array = new String[] { "a", "bc" ,"dc" ,"a", "ef" };
System.out.println(Arrays.toString(array));
Set<String> asSet = new HashSet<String>(Arrays.asList(array));
asSet.remove("a");
array = asSet.toArray(new String[] {});
System.out.println(Arrays.toString(array));
Gives:
[a, bc, dc, a, ef]
[dc, ef, bc]
Where as the current accepted answer from Chris Yester Young outputs:
[a, bc, dc, a, ef]
[bc, dc, ef, null, ef]
with the code
String[] array = new String[] { "a", "bc" ,"dc" ,"a", "ef" };
System.out.println(Arrays.toString(array));
List<String> list = new ArrayList<String>(Arrays.asList(array));
list.removeAll(Arrays.asList("a"));
array = list.toArray(array);
System.out.println(Arrays.toString(array));
without any null values left behind.
My little contribution to this problem.
public class DeleteElementFromArray {
public static String foo[] = {"a","cc","a","dd"};
public static String search = "a";
public static void main(String[] args) {
long stop = 0;
long time = 0;
long start = 0;
System.out.println("Searched value in Array is: "+search);
System.out.println("foo length before is: "+foo.length);
for(int i=0;i<foo.length;i++){ System.out.println("foo["+i+"] = "+foo[i]);}
System.out.println("==============================================================");
start = System.nanoTime();
foo = removeElementfromArray(search, foo);
stop = System.nanoTime();
time = stop - start;
System.out.println("Equal search took in nano seconds = "+time);
System.out.println("==========================================================");
for(int i=0;i<foo.length;i++){ System.out.println("foo["+i+"] = "+foo[i]);}
}
public static String[] removeElementfromArray( String toSearchfor, String arr[] ){
int i = 0;
int t = 0;
String tmp1[] = new String[arr.length];
for(;i<arr.length;i++){
if(arr[i] == toSearchfor){
i++;
}
tmp1[t] = arr[i];
t++;
}
String tmp2[] = new String[arr.length-t];
System.arraycopy(tmp1, 0, tmp2, 0, tmp2.length);
arr = tmp2; tmp1 = null; tmp2 = null;
return arr;
}
}
It depends on what you mean by "remove"? An array is a fixed size construct - you can't change the number of elements in it. So you can either a) create a new, shorter, array without the elements you don't want or b) assign the entries you don't want to something that indicates their 'empty' status; usually null if you are not working with primitives.
In the first case create a List from the array, remove the elements, and create a new array from the list. If performance is important iterate over the array assigning any elements that shouldn't be removed to a list, and then create a new array from the list. In the second case simply go through and assign null to the array entries.
Arrgh, I can't get the code to show up correctly. Sorry, I got it working. Sorry again, I don't think I read the question properly.
String foo[] = {"a","cc","a","dd"},
remove = "a";
boolean gaps[] = new boolean[foo.length];
int newlength = 0;
for (int c = 0; c<foo.length; c++)
{
if (foo[c].equals(remove))
{
gaps[c] = true;
newlength++;
}
else
gaps[c] = false;
System.out.println(foo[c]);
}
String newString[] = new String[newlength];
System.out.println("");
for (int c1=0, c2=0; c1<foo.length; c1++)
{
if (!gaps[c1])
{
newString[c2] = foo[c1];
System.out.println(newString[c2]);
c2++;
}
}
Will copy all elements except the one with index i:
if(i == 0){
System.arraycopy(edges, 1, copyEdge, 0, edges.length -1 );
}else{
System.arraycopy(edges, 0, copyEdge, 0, i );
System.arraycopy(edges, i+1, copyEdge, i, edges.length - (i+1) );
}
If it doesn't matter the order of the elements. you can swap between the elements foo[x] and foo[0], then call foo.drop(1).
foo.drop(n) removes (n) first elements from the array.
I guess this is the simplest and resource efficient way to do.
PS: indexOf can be implemented in many ways, this is my version.
Integer indexOf(String[] arr, String value){
for(Integer i = 0 ; i < arr.length; i++ )
if(arr[i] == value)
return i; // return the index of the element
return -1 // otherwise -1
}
while (true) {
Integer i;
i = indexOf(foo,"a")
if (i == -1) break;
foo[i] = foo[0]; // preserve foo[0]
foo.drop(1);
}
to remove only the first of several equal entries
with a lambda
boolean[] done = {false};
String[] arr = Arrays.stream( foo ).filter( e ->
! (! done[0] && Objects.equals( e, item ) && (done[0] = true) ))
.toArray(String[]::new);
can remove null entries
In an array of Strings like
String name = 'a b c d e a f b d e' // could be like String name = 'aa bb c d e aa f bb d e'
I build the following class
class clearname{
def parts
def tv
public def str = ''
String name
clearname(String name){
this.name = name
this.parts = this.name.split(" ")
this.tv = this.parts.size()
}
public String cleared(){
int i
int k
int j=0
for(i=0;i<tv;i++){
for(k=0;k<tv;k++){
if(this.parts[k] == this.parts[i] && k!=i){
this.parts[k] = '';
j++
}
}
}
def str = ''
for(i=0;i<tv;i++){
if(this.parts[i]!='')
this.str += this.parts[i].trim()+' '
}
return this.str
}}
return new clearname(name).cleared()
getting this result
a b c d e f
hope this code help anyone
Regards
Assign null to the array locations.
I have one Arraylist of String and I have added Some Duplicate Value in that. and i just wanna remove that Duplicate value So how to remove it.
Here Example I got one Idea.
List<String> list = new ArrayList<String>();
list.add("Krishna");
list.add("Krishna");
list.add("Kishan");
list.add("Krishn");
list.add("Aryan");
list.add("Harm");
System.out.println("List"+list);
for (int i = 1; i < list.size(); i++) {
String a1 = list.get(i);
String a2 = list.get(i-1);
if (a1.equals(a2)) {
list.remove(a1);
}
}
System.out.println("List after short"+list);
But is there any Sufficient way remove that Duplicate form list. with out using For loop ?
And ya i can do it by using HashSet or some other way but using array list only.
would like to have your suggestion for that. thank you for your answer in advance.
You can create a LinkedHashSet from the list. The LinkedHashSet will contain each element only once, and in the same order as the List. Then create a new List from this LinkedHashSet. So effectively, it's a one-liner:
list = new ArrayList<String>(new LinkedHashSet<String>(list))
Any approach that involves List#contains or List#remove will probably decrease the asymptotic running time from O(n) (as in the above example) to O(n^2).
EDIT For the requirement mentioned in the comment: If you want to remove duplicate elements, but consider the Strings as equal ignoring the case, then you could do something like this:
Set<String> toRetain = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
toRetain.addAll(list);
Set<String> set = new LinkedHashSet<String>(list);
set.retainAll(new LinkedHashSet<String>(toRetain));
list = new ArrayList<String>(set);
It will have a running time of O(n*logn), which is still better than many other options. Note that this looks a little bit more complicated than it might have to be: I assumed that the order of the elements in the list may not be changed. If the order of the elements in the list does not matter, you can simply do
Set<String> set = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
set.addAll(list);
list = new ArrayList<String>(set);
if you want to use only arraylist then I am worried there is no better way which will create a huge performance benefit. But by only using arraylist i would check before adding into the list like following
void addToList(String s){
if(!yourList.contains(s))
yourList.add(s);
}
In this cases using a Set is suitable.
You can make use of Google Guava utilities, as shown below
list = ImmutableSet.copyOf(list).asList();
This is probably the most efficient way of eliminating the duplicates from the list and interestingly, it preserves the iteration order as well.
UPDATE
But, in case, you don't want to involve Guava then duplicates can be removed as shown below.
ArrayList<String> list = new ArrayList<String>();
list.add("Krishna");
list.add("Krishna");
list.add("Kishan");
list.add("Krishn");
list.add("Aryan");
list.add("Harm");
System.out.println("List"+list);
HashSet hs = new HashSet();
hs.addAll(list);
list.clear();
list.addAll(hs);
But, of course, this will destroys the iteration order of the elements in the ArrayList.
Shishir
Java 8 stream function
You could use the distinct function like above to get the distinct elements of the list,
stringList.stream().distinct();
From the documentation,
Returns a stream consisting of the distinct elements (according to Object.equals(Object)) of this stream.
Another way, if you do not wish to use the equals method is by using the collect function like this,
stringList.stream()
.collect(Collectors.toCollection(() ->
new TreeSet<String>((p1, p2) -> p1.compareTo(p2))
));
From the documentation,
Performs a mutable reduction operation on the elements of this stream using a Collector.
Hope that helps.
Simple function for removing duplicates from list
private void removeDuplicates(List<?> list)
{
int count = list.size();
for (int i = 0; i < count; i++)
{
for (int j = i + 1; j < count; j++)
{
if (list.get(i).equals(list.get(j)))
{
list.remove(j--);
count--;
}
}
}
}
Example:
Input: [1, 2, 2, 3, 1, 3, 3, 2, 3, 1, 2, 3, 3, 4, 4, 4, 1]
Output: [1, 2, 3, 4]
List<String> list = new ArrayList<String>();
list.add("Krishna");
list.add("Krishna");
list.add("Kishan");
list.add("Krishn");
list.add("Aryan");
list.add("Harm");
HashSet<String> hs=new HashSet<>(list);
System.out.println("=========With Duplicate Element========");
System.out.println(list);
System.out.println("=========Removed Duplicate Element========");
System.out.println(hs);
I don't think the list = new ArrayList<String>(new LinkedHashSet<String>(list)) is not the best way , since we are using the LinkedHashset(We could use directly LinkedHashset instead of ArrayList),
Solution:
import java.util.ArrayList;
public class Arrays extends ArrayList{
#Override
public boolean add(Object e) {
if(!contains(e)){
return super.add(e);
}else{
return false;
}
}
public static void main(String[] args) {
Arrays element=new Arrays();
element.add(1);
element.add(2);
element.add(2);
element.add(3);
System.out.println(element);
}
}
Output:
[1, 2, 3]
Here I am extending the ArrayList , as I am using the it with some changes by overriding the add method.
public List<Contact> removeDuplicates(List<Contact> list) {
// Set set1 = new LinkedHashSet(list);
Set set = new TreeSet(new Comparator() {
#Override
public int compare(Object o1, Object o2) {
if(((Contact)o1).getId().equalsIgnoreCase(((Contact)2).getId()) ) {
return 0;
}
return 1;
}
});
set.addAll(list);
final List newList = new ArrayList(set);
return newList;
}
This will be the best way
List<String> list = new ArrayList<String>();
list.add("Krishna");
list.add("Krishna");
list.add("Kishan");
list.add("Krishn");
list.add("Aryan");
list.add("Harm");
Set<String> set=new HashSet<>(list);
It is better to use HastSet
1-a) A HashSet holds a set of objects, but in a way that it allows you to easily and quickly determine whether an object is already in the set or not. It does so by internally managing an array and storing the object using an index which is calculated from the hashcode of the object. Take a look here
1-b) HashSet is an unordered collection containing unique elements. It has the standard collection operations Add, Remove, Contains, but since it uses a hash-based implementation, these operation are O(1). (As opposed to List for example, which is O(n) for Contains and Remove.) HashSet also provides standard set operations such as union, intersection, and symmetric difference.Take a look here
2) There are different implementations of Sets. Some make insertion and lookup operations super fast by hashing elements. However that means that the order in which the elements were added is lost. Other implementations preserve the added order at the cost of slower running times.
The HashSet class in C# goes for the first approach, thus not preserving the order of elements. It is much faster than a regular List. Some basic benchmarks showed that HashSet is decently faster when dealing with primary types (int, double, bool, etc.). It is a lot faster when working with class objects. So that point is that HashSet is fast.
The only catch of HashSet is that there is no access by indices. To access elements you can either use an enumerator or use the built-in function to convert the HashSet into a List and iterate through that.Take a look here
Without a loop, No! Since ArrayList is indexed by order rather than by key, you can not found the target element without iterate the whole list.
A good practice of programming is to choose proper data structure to suit your scenario. So if Set suits your scenario the most, the discussion of implementing it with List and trying to find the fastest way of using an improper data structure makes no sense.
public static void main(String[] args) {
#SuppressWarnings("serial")
List<Object> lst = new ArrayList<Object>() {
#Override
public boolean add(Object e) {
if(!contains(e))
return super.add(e);
else
return false;
}
};
lst.add("ABC");
lst.add("ABC");
lst.add("ABCD");
lst.add("ABCD");
lst.add("ABCE");
System.out.println(lst);
}
This is the better way
list = list.stream().distinct().collect(Collectors.toList());
This could be one of the solutions using Java8 Stream API. Hope this helps.
public void removeDuplicates() {
ArrayList<Object> al = new ArrayList<Object>();
al.add("java");
al.add('a');
al.add('b');
al.add('a');
al.add("java");
al.add(10.3);
al.add('c');
al.add(14);
al.add("java");
al.add(12);
System.out.println("Before Remove Duplicate elements:" + al);
for (int i = 0; i < al.size(); i++) {
for (int j = i + 1; j < al.size(); j++) {
if (al.get(i).equals(al.get(j))) {
al.remove(j);
j--;
}
}
}
System.out.println("After Removing duplicate elements:" + al);
}
Before Remove Duplicate elements:
[java, a, b, a, java, 10.3, c, 14, java, 12]
After Removing duplicate elements:
[java, a, b, 10.3, c, 14, 12]
Using java 8:
public static <T> List<T> removeDuplicates(List<T> list) {
return list.stream().collect(Collectors.toSet()).stream().collect(Collectors.toList());
}
In case you just need to remove the duplicates using only ArrayList, no other Collection classes, then:-
//list is the original arraylist containing the duplicates as well
List<String> uniqueList = new ArrayList<String>();
for(int i=0;i<list.size();i++) {
if(!uniqueList.contains(list.get(i)))
uniqueList.add(list.get(i));
}
Hope this helps!
private static void removeDuplicates(List<Integer> list)
{
Collections.sort(list);
int count = list.size();
for (int i = 0; i < count; i++)
{
if(i+1<count && list.get(i)==list.get(i+1)){
list.remove(i);
i--;
count--;
}
}
}
public static List<String> removeDuplicateElements(List<String> array){
List<String> temp = new ArrayList<String>();
List<Integer> count = new ArrayList<Integer>();
for (int i=0; i<array.size()-2; i++){
for (int j=i+1;j<array.size()-1;j++)
{
if (array.get(i).compareTo(array.get(j))==0) {
count.add(i);
int kk = i;
}
}
}
for (int i = count.size()+1;i>0;i--) {
array.remove(i);
}
return array;
}
}
I have 3 arraylist each have size = 3 and 3 arrays also have length = 3 of each. I want to copy data from arraylists to arrays in following way but using any loop (i.e for OR for each).
myArray1[1] = arraylist1.get(1);
myArray1[2] = arraylist2.get(1);
myArray1[3] = arraylist3.get(1);
I have done it manually one by one without using any loop, but code appears to be massive because in future I'm sure that number of my arraylists and arrays will increase up to 15.
I want to copy the data from arraylists to arrays as shown in the image but using the loops not manually one by one?
How about this?
List<Integer> arraylist0 = Arrays.asList(2,4,3);
List<Integer> arraylist1 = Arrays.asList(2,5,7);
List<Integer> arraylist2 = Arrays.asList(6,3,7);
List<List<Integer>> arraylistList = Arrays.asList(arraylist0, arraylist1, arraylist2);
int size = 3;
int[] myArray0 = new int[size];
int[] myArray1 = new int[size];
int[] myArray2 = new int[size];
int[][] myBigArray = new int[][] {myArray0, myArray1, myArray2};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
myBigArray[i][j] = arraylistList.get(j).get(i);
}
}
To explain, since we want to be able to work with an arbitrary size (3, 15, or more), we are dealing with 2-dimensional data.
We are also dealing with array and List, which are slightly different in their use.
The input to your problem is List<Integer>, and so we make a List<List<Integer>> in order to deal with all the input data easily.
Similarly, the output will be arrays, so we make a 2-dimensional array (int[][]) in order to write the data easily.
Then it's simply a matter of iterating over the data in 2 nested for loops. Notice that this line reverses the order of i and j in order to splice the data the way you intend.
myBigArray[i][j] = arraylistList.get(j).get(i);
And then you can print your answer like this:
System.out.println(Arrays.toString(myArray0));
System.out.println(Arrays.toString(myArray1));
System.out.println(Arrays.toString(myArray2));
You need to have two additional structures:
int[][] destination = new int [][] {myArray1, myArray2,myArray3 }
List<Integer>[] source;
source = new List<Integer>[] {arraylist1,arraylist2,arraylist3}
myArray1[1] = arraylist1.get(1);
myArray1[2] = arraylist2.get(1);
myArray1[3] = arraylist3.get(1);
for (int i=0;i<destination.length;i++) {
for (int j=0;j<source.length;j++) {
destination[i][j] = source[j].get(i);
}
}
If you cannot find a ready made API or function for this, I would suggest trivializing the conversion from List to Array using the List.toArray() method and focus on converting/transforming the given set of lists to a another bunch of lists which contain the desired output. Following is a code sample which I would think achieves this. It does assume the input lists are NOT of fixed/same sizes. Assuming this would only make the logic easier.
On return of this function, all you need to do is to iterate over the TreeMap and convert the values to arrays using List.toArray().
public static TreeMap<Integer, List<Integer>> transorm(
List<Integer>... lists) {
// Return a blank TreeMap if not input. TreeMap explanation below.
if (lists == null || lists.length == 0)
return new TreeMap<>();
// Get Iterators for the input lists
List<Iterator<Integer>> iterators = new ArrayList<>();
for (List<Integer> list : lists) {
iterators.add(list.iterator());
}
// Initialize Return. We return a TreeMap, where the key indicates which
// position's integer values are present in the list which is the value
// of this key. Converting the lists to arrays is trivial using the
// List.toArray() method.
TreeMap<Integer, List<Integer>> transformedLists = new TreeMap<>();
// Variable maintaining the position for which values are being
// collected. See below.
int currPosition = 0;
// Variable which keeps track of the index of the iterator currently
// driving the iteration and the driving iterator.
int driverItrIndex = 0;
Iterator<Integer> driverItr = lists[driverItrIndex].iterator();
// Actual code that does the transformation.
while (driverItrIndex < iterators.size()) {
// Move to next driving iterator
if (!driverItr.hasNext()) {
driverItrIndex++;
driverItr = iterators.get(driverItrIndex);
continue;
}
// Construct Transformed List
ArrayList<Integer> transformedList = new ArrayList<>();
for (Iterator<Integer> iterator : iterators) {
if (iterator.hasNext()) {
transformedList.add(iterator.next());
}
}
// Add to return
transformedLists.put(currPosition, transformedList);
}
// Return Value
return transformedLists;
}
I want to get specific combination of permutation of string like alphabet. To understand me, I'll show you the code that I using:
public class PermutationExample {
public static List<String> getPermutation(String input) {
List<String> collection = null;
if (input.length() == 1) {
collection = new ArrayList<String>();
collection.add(input);
return collection;
} else {
collection = getPermutation(input.substring(1));
Character first = input.charAt(0);
List<String> result = new ArrayList<String>();
for (String str : collection) {
for (int i = 0; i < str.length(); i++) {
String item = str.substring(0, i) + first
+ str.substring(i);
result.add(item);
}
String item = str.concat(first.toString());
result.add(item);
}
return result;
}
}
public static void main(String[] args) {
System.out.println(PermutationExample.getPermutation("ABCD"));
}
}
This code works well and i can get every combination, I can take it from the list, if I need 5-th element, I can receive it. But if the string is the alphabet ... , didn't works, it's too big. What I have to do, to get the specific element like 1221-th from all 26! combinations ?
I solved a similar problem a while ago, only in python.
If what you need is simply the n-th permutation, then you can do a lot better then generating every permutation and returning the n-th, if you try to think about generating only the permutation you need.
You can do this "simply" by figuring out what should be the element in front for the number of permutations you want, and then what should be the remaining of the elements recursively.
Assume a collection of values [0, ... ,X], for any values such that col[n] < col[n+1]
For N elements, there are N! possible permutations, the case when the collection will be perfectly reversed.
We will see the change in the head of the collection after each (N-1)! permutations, so if n < (N-1)!, the head is the head. You then have a remaining number of permutations, and you can apply the same logic recursively.
Does this help? I know it's fairly high level and you'll have to think a bit about it, but maybe it'll get you on the right track.
I have a list of strings in my (Android) Java program, and I need to get the index of an object in the list. The problem is, I can only find documentation on how to find the first and last index of an object. What if I have 3 or more of the same object in my list? How can I find every index?
Thanks!
You need to do a brute force search:
static <T> List<Integer> indexesOf(List<T> source, T target)
{
final List<Integer> indexes = new ArrayList<Integer>();
for (int i = 0; i < source.size(); i++) {
if (source.get(i).equals(target)) { indexes.add(i); }
}
return indexes;
}
Note that this is not necessarily the most efficient approach. Depending on the context and the types/sizes of lists, you might need to do some serious optimizations. The point is, if you need every index (and know nothing about the structure of the list contents), then you need to do a deathmarch through every item for at best O(n) cost.
Depending on the type of the underlying list, get(i) may be O(1) (ArrayList) or O(n) (LinkedList), so this COULD blow up to a O(n2) implementation. You could copy to an ArrayList, or you could walk the LinkedList incrementing an index counter manually.
If documentation is not helping me in my logic in this situation i would have gone for a raw approach for Traversing the list in a loop and saving the index where i found a match
ArrayList<String> obj = new ArrayList<String>();
obj.add("Test Data"): // fill the list with your data
String dataToFind = "Hello";
ArrayList<Integer> intArray = new ArrayList<Integer>();
for(int i = 0 ; i<obj.size() ; i++)
{
if(obj.get(i).equals(dataToFind)) intArray.add(i);
}
now intArray would have contained all the index of matched element in the list
An alternative brute force approach that will also find all null indexes:
static List<Integer> indexesOf(List<?> list, Object target) {
final List<Integer> indexes = new ArrayList<Integer>();
int offset = 0;
for (int i = list.indexOf(target); i != -1; i = list.indexOf(target)) {
indexes.add(i + offset);
list = list.subList(i + 1, list.size());
offset += i + 1;
}
return indexes;
}