0

Below is my array....

["AAA", "BBB", "CCC", "AAA", "BBB", "CCC", "AAA", "BBB", "CCC", "DDD"]

What can I do to get a array back like ["AAA", "BBB", "CCC"]

for example, if the first element is "AAA", I want to delete all element after second "AAA"(second "AAA" also remove)

Thanks.

Dreams
  • 8,288
  • 10
  • 45
  • 71

6 Answers6

2

You can do this easily using indexOf and slice methods of array in javascript.

var arr = ["AAA", "BBB", "CCC", "AAA", "BBB", "CCC", "AAA", "BBB", "CCC", "DDD"];
var firstElem = arr[0];
var secondIndex = arr.indexOf(firstElem, 1);

// Output: ["AAA", "BBB", "CCC"]
var newArr = (secondIndex != -1) ? arr.slice(0, secondIndex) : arr;

Working Fiddle: https://jsfiddle.net/4f25wyaj/2/

Siva
  • 1,123
  • 2
  • 14
  • 25
  • 5
    This is good, but note that if the first element *doesn't* repeat the result will be an array keeping all of the original elements except the last one. – nnnnnn Sep 23 '16 at 04:43
  • @nnnnnn—but that's what the OP wants. – RobG Sep 23 '16 at 04:54
  • 2
    @RobG - The OP doesn't say what to do if the first element doesn't repeat, but it seems unlikely that removing just the last item via `.slice(0,-1)` would be the right thing in that case. – nnnnnn Sep 23 '16 at 05:12
0

You can use Array.prototype.filter(), reference first element of array to check if the value has been iterated

var arr = ["AAA", "BBB", "CCC", "AAA", "BBB", "CCC", "AAA", "BBB", "CCC", "DDD"]

var again = false;

arr = arr.filter(function(el, index) {
  return !again && (again = index > 0 && el === arr[0], !again);
});

console.log(arr);
guest271314
  • 1
  • 15
  • 104
  • 177
  • Why not `var newArr = arr.slice(arr.indexOf(arr[0], 1))`. – RobG Sep 23 '16 at 04:56
  • @RobG _"Why not `var newArr = arr.slice(arr.indexOf(arr[0], 1))`"_ Appears to return `["AAA", "BBB", "CCC", "AAA", "BBB", "CCC", "DDD"]`? – guest271314 Sep 23 '16 at 05:05
  • @Bergi `this` passed to `.map()` or `.filter()` callback returns object, not value. `arr = arr.filter(function(el, index) { return !again && (again = index > 0 && el === arr[0], !again); })` returns same result – guest271314 Sep 23 '16 at 06:14
  • The proper fix for that would to use a strict function or loose comparison, not `valueOf`. And yes, passing in a context is pretty superfluous when you can just refer to the `arr[0]` element directly. – Bergi Sep 23 '16 at 06:16
  • @Bergi Updated post to use `arr[0]`. What is issue with using `valueOf`? – guest271314 Sep 23 '16 at 06:17
  • Ah, sliced the wrong end! `arr.slice(0, arr.indexOf(arr[0], 1))` ;-) – RobG Sep 23 '16 at 09:47
0

Faster implementation (Better for short or medium size arrays):

var a = ["AAA", "BBB", "CCC", "AAA", "BBB", "CCC", "AAA", "BBB", "CCC", "DDD"];

// Faster implementation:
// (Better for short or medium size arrays)
var b = a.filter((function(){
    var idx = {};
    var cont = true; // Continue
    return function (item){
        if (! cont) return false;
        if (idx[item]) return cont = false;
        return idx[item] = true;
    };
})());

console.log(b);
// [ 'AAA', 'BBB', 'CCC' ]

Implementation with minimal memory waste (but highly unefficient):

// Minimal memory waste implementation:
var b = a.filter((function(){
    var cont = true; // Continue
    return function (item, i){
        if (! cont) return false;
        if (a.slice(0, i).filter(x=>x==item).length) return cont = false;
        return true;
    };  
})());

console.log(b);
// [ 'AAA', 'BBB', 'CCC' ]

Of course, there is infinite intermediate approaches (depending on your needings). But, If you donsn't need to parse HUGE arrays, the best solution is to use the first approach: Index will be freed by garbage collector as soon as filter process finishes and, in fact, if you are lucky and repetition happen early, then no much memory will be used ;-)

bitifet
  • 3,514
  • 15
  • 37
  • Instead of `filter(…).length` you you want to use `some(…)`. Or just use `indexOf`, it even takes a starting position. – Bergi Sep 23 '16 at 06:14
  • For huge arrays, an even better solution would be not to use `filter` at all, because you likely wouldn't need to iterate through the whole array. Just stop when you have the slice you need. – Bergi Sep 23 '16 at 06:20
  • Maybe yes or maybe not: `.some()` was standarizend in ECMA-262 (early June 2016) so, depending on where you want to execute it, you would need a polyfill. Even, of course, some() will stop at first match avoiding a bit of extra process at the end. – bitifet Sep 23 '16 at 06:29
  • Both `filter` and `some` were standardised at the same time, in ES5 (2011) - and had been around in FF since 2005. – Bergi Sep 23 '16 at 06:31
  • About your second comment, You are totally right. This was only a fast rewrite of the first approach (which is the best for me in most cases). But if we need to parse an huge array, then we probably should not only stop at first match, but totally avoid not strictly necessary function calls. ;-) – bitifet Sep 23 '16 at 06:32
0

Quick and dirty using jQuery each() function.

each() goes through the array and adds elements to new array until a duplicate of the first element is found.

var arr = ["AAA", "BBB", "CCC", "AAA", "BBB", "CCC", "AAA", "BBB", "CCC", "DDD"];
var newArray = [];
$.each(arr, function(i, el){
    if($.inArray(el, newArray) === -1) 
      newArray.push(el);
    else if (el == arr[0])
      return false
});
arr = newArray;
// Formatted array is in "arr"
alert(arr);
Zirbo Filip
  • 300
  • 1
  • 13
  • Hardly quick. Why on earth would you use jQuery *each* when the built–in *forEach* is available? If you want IE8 support, you have to go back to jQuery 1.12. Better to use a [*polyfill*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach). – RobG Sep 23 '16 at 09:52
  • You have 68k reputation, you should know better that it's not about optimization, it's about solving the problem. This is not "the best solution". This is a solution. – Zirbo Filip Sep 23 '16 at 09:57
-1

Though Your question is not fully clear but still as per my understanding I am providing following solutions

Solution 1:
 Assumption: You have a list of input and a pointer which shows the last index till you want to pick the input data.

    public static void main(String[] args) {
        String input[] = { "AAA", "BBB", "CCC", "AAA", "BBB", "CCC", "AAA", "BBB", "CCC", "DDD" };
        String output[]= new String[5];
        int stopByIndex =3;

        for(int i=0;i<stopByIndex;i++){
            output[i]=input[i];
        }
        System.out.println(output);
    }


 Solution 2:
Assumption: Print elements which occurred multiple times:

  public static void main(String[] args) {
    String input[] = { "AAA", "BBB", "CCC", "AAA", "BBB", "CCC", "AAA", "BBB", "CCC", "DDD" };
    List<String> output = new ArrayList<>();
    Map<String, Integer> keyWithCount = new HashMap<String, Integer>();
    int stopByIndex = 3;

    for (String str : input) {
        if (keyWithCount.containsKey(str)) {
            keyWithCount.put(str, keyWithCount.get(str) + 1);
        } else {
            keyWithCount.put(str, 1);
        }
    }

    Iterator<Entry<String, Integer>> itr = keyWithCount.entrySet().iterator();
    while (itr.hasNext()) {
        Entry<String, Integer> entry = itr.next();

        if (entry.getValue() > 1) {
            output.add(entry.getKey());
        }
    }

    System.out.println(output);
}
Ankur Gupta
  • 301
  • 4
  • 12
-1

Try this:

var arr = ["AAA", "BBB", "CCC", "AAA", "BBB", "CCC", "AAA", "BBB", "CCC",     "DDD"];

arr.splice(3)
  • 1
    How did you guess that first repetition will always be at fourth position? :LOL: – bitifet Sep 23 '16 at 06:11
  • Why not just try `var arr = ["AAA", "BBB", "CCC"];`? That gets us the result without any inperformant splicing. – Bergi Sep 23 '16 at 06:12