Array of unique elements?
Asked Answered
H

7

17

Given an array like the one below, I was wondering if there is an easy way to turn this array into an array with unique values only?

This is given:

   numbers={5,5,4,3,1,4,5,4,5} 

Turn it into a result array like this, preserving the original order:

   {5,1,2,3,4} 
Huntingdonshire answered 1/2, 2013 at 22:34 Comment(5)
Is it always sorted? Yes, there's an easy way, but what have you tried?Shroudlaid
No it is not sorted in all cases.Huntingdonshire
docs.oracle.com/javase/7/docs/api/java/util/Set.htmlPaterfamilias
@MHZ: Does the order of the resulting array matter? E.g. should the ordering from the first array be preserved?Shroudlaid
No the order of the resulting array, does not matter, as long as all element are unique.Huntingdonshire
G
31

In Java 8, use IntStream to get unique elements of an array

int[] noDuplicates = IntStream.of(array).distinct().toArray();

The simplest way would be to create set from the array.

Integer[] array = ...
Set<Integer> set = new LinkedHashSet<Integer>(Arrays.asList(array ));

and then you can retrieve the array using:

set.toArray()

use LinkedHashSet if you want to maintain the order or TreeSet if you want to have it sorted.

Gardenia answered 1/2, 2013 at 22:36 Comment(2)
I am working with strings and I was getting, HashSet<String> cannot be resolved to a type.Huntingdonshire
it means that you need to import the HashSet, simply add import java.util.HashSet; you should consider using and IDE like EclipseGardenia
D
3

Two options

  1. Keep a map of count and element and finally only use those elements with count 1. (Need extra storage but is faster)

  2. Sort the array and as you move through the array only use non-repeated ones.

Doesn't need extra space but will be O(n lg(n))

Durant answered 1/2, 2013 at 22:37 Comment(3)
Option 1's time complexity might not be faster. If you're using a balanced binary search tree for the map, you will get lg(N) operations. If you use a hash table, you are acting under the uniform hashing assumption.Nilla
I was assuming a hash table. And all standard languages have v. good hashing functions which more or less ensure O(1) insert and retrieveDurant
OK. I suppose that since it's numbers it's fine. It's not hard to make a hash for an int :). The size for the hash table will be important, though, as you will have to cycle through all of the values stored in it, which is O(M), where M is the size of the hash table. Good, fast answer, anyway, so +1.Nilla
M
1

Supposing an array of Objects:

Object[] arr;

{...omissis...}

List<Object> list = new ArrayList<Object>();
for(Object val: arr) {
  if(!list.contains(val)) {
    list.add(val);
  }
}
list.toArray(new Object[0]);

Replace Object with your Array Class if needed.

Mutualism answered 1/2, 2013 at 22:41 Comment(3)
Thanks for the reply. I am using arrays not array lists.Huntingdonshire
@MHZ this works even with arrays so arr is an array of objects, I edit my postMutualism
This is a very expensive way to do it, as list.contains() is linearly increasing effort as the list grows. With very large lists this can be a difference like a few seconds compared to thousands of years processing time... Better use a HashSet for contains lookup and the List for result buildup, if you want to keep this approach.Pastel
N
1

Here are 2 ideas:

  1. Add all items to a Set, or create one with the constructor that has an array as a parameter (HashSet or TreeSet, depending on what time complexity you want). Then, for each element in the set, remove it, adding it to the next open position of a new array that is the size of the set.

  2. Sort the array. Add the object at index 0 to an ArrayList. Start at index 1 and go to index length - 1. If the current element is not equal to the element at the previous index, add it to the ArrayList. Change the ArrayList into an array, if necessary.

Nilla answered 1/2, 2013 at 22:43 Comment(0)
P
0

(Repost of: https://mcmap.net/q/568758/-how-to-get-unique-values-from-array)

Using the Stream API of Java 8 this is a solution with a generic Array type:

public static <T> T[] makeUnique(T... values)
{
    return Arrays.stream(values).distinct().toArray(new IntFunction<T[]>()
    {

        @Override
        public T[] apply(int length)
        {
            return (T[]) Array.newInstance(values.getClass().getComponentType(), length);
        }

    });
}

It works for any Object type array, but not for primitive arrays.

For primitive arrays it looks like this:

public static int[] makeUnique(int... values)
{
    return Arrays.stream(values).distinct().toArray();
}

And finally here is a little unit test:

@Test
public void testMakeUnique()
{
    assertArrayEquals(new String[] { "a", "b", "c" }, makeUnique("a", "b", "c", "b", "a"));
    assertArrayEquals(new Object[] { "a", "b", "c" }, makeUnique(new Object[] { "a", "b", "c", "b", "a" }));
    assertArrayEquals(new Integer[] { 1, 2, 3, 4, 5 }, makeUnique(new Integer[] { 1, 2, 2, 3, 3, 3, 1, 4, 5, 5, 5, 1 }));
    assertArrayEquals(new int[] { 1, 2, 3, 4, 5 }, makeUnique(new int[] { 1, 2, 2, 3, 3, 3, 1, 4, 5, 5, 5, 1 }));
}
Pastel answered 27/9, 2016 at 18:12 Comment(0)
F
0

If you want to merge two list without duplicates then try this one, it works for me.

    List<Name> list1 = Arrays.asList(new Name("abc", 1), new Name("def", 2), new Name("ghi", 3));
    List<Name> list2 = Arrays.asList(new Name("def", 4), new Name("jkl", 5), new Name("mno", 6));
   
    List<Name> newNameList= new ArrayList<>(Stream.of(list1, list2).flatMap(List::stream)
            .collect(Collectors.toMap(Name::getName, d -> d, (Name x, Name y) -> x == null ? y : x)).values());
    newNameList.forEach(System.out::println);


class Name {
String name;
int id;

public Name(String name, int id) {
    this.name = name;
    this.id = id;
}

public String getName() {
    return name;
}

@Override
public String toString() {
    return "Name{" + "name='" + name + '\'' + ", id=" + id + '}';
}
}
Finis answered 2/4, 2021 at 12:33 Comment(0)
D
0
    boolean isunique=false;
       int i, j;
       for(i=0;i<n;i++)
       {
            for(j=0;j<i;j++) 
                 if(a[i]==a[j]) 
                      break;
            if(i==j) 
              System.out.print(a[i]+" ");
Dawnedawson answered 4/12, 2023 at 10:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.