2016-01-16 11 views
8

mam tablicą JavaScript jak:Pobieranie JavaScript elementy rzędu tablicy po wystąpieniu elementu

var myArray = ['a', 'x', 'b', 'x', 'x', 'p', 'y', 'x', 'x', 'b', 'x', 'x']; 

że chce pobrać tylko tych elementów macierzy, które pochodzą od 2 konsekwencji występowania danego elementu.

czyli w powyższej tablicy, chcę, aby pobrać wszystkie elementy, które przychodzą po konsekwencji 'x', 'x'

Więc moje wyjście powinno być:

'p' 
'b' 

Mam rozwiązanie jak:

var arrLength = myArray.length; 
for (var i = 0; i < arrLength; i++) { 
    if(i+2 < arrLength && myArray[i] == 'x' && myArray[i+1] == 'x') { 
     console.log(myArray[i+2]); 
    } 
}; 

To spełnia moje potrzeby, ale nie jest tak ogólne.

Na przykład. jeśli muszę sprawdzić 3 kolejne wystąpienia, to znowu muszę dodać warunek wewnątrz , jeśli dla myArray[i+2] == 'x' i tak dalej.

Czy ktoś może zapewnić lepszy sposób na pobranie elementów?

+2

Co jeśli masz 4 "x"? Jeśli trzecia została pobrana? Czy 3 i 4rt pobierają następujący przedmiot? – Oriol

+1

Czy elementy tablicy są zawsze pojedynczymi literami? Jest to zasadniczo problem z ciągami (z wieloma dobrymi i wydajnymi rozwiązaniami), chociaż żaden z nich nie jest natywnie implementowany na 'Array' – Bergi

+0

@Bergi, chcę ogólne rozwiązanie, więc ta tablica może zawierać pojedynczą literę lub może być tablicą łańcuchów . –

Odpowiedz

5

Funkcjonalny sposób polegałby na rekursji. Z rozprzestrzenianiem ES6, można dość dużo naśladować jędrność prawdziwie „funkcjonalnej” języku :-)

var myArray = ['a', 'x', 'b', 'x', 'x', 'p', 'y', 'x', 'x', 'b', 'x', 'x']; 

function reducer(acc, xs) { 
    if (xs.length > 2) { 
     if (xs[0] === xs[1]) { 
      // add the third element to accumulator 
      // remove first three elements from xs 
      // return reducer([xs[2], ...acc], xs.slice(3)); 
      // or per Nina's question below 
      return reducer([xs[2], ...acc], xs.slice(1)); 
     } else { 
      // remove first element from xs and recurse 
      return reducer(acc, xs.slice(1)) 
     } 
    } else { 
     return acc; 
    } 
} 

console.log(reducer([], myArray)); 
+0

ok, wolę funkcjonalność ponad imperatyw –

+0

Rekursja jest silnie powtarzającym się mechanizmem w językach funkcjonalnych. I ten kod naprawdę dobrze naśladuje funkcjonalne programowanie - nie ma kodu proceduralnego/imperatywnego z wyjątkiem 'slice()', który i tak może być odtworzony w językach funkcjonalnych. – Purag

+0

proszę przetestować tę tablicę: '['a', 'x', 'b', 'x', 'x', 'x', 'p', 'y', 'x', 'x', 'b ',' x ',' x '] 'z potrójnym'' x'', oczekiwany wynik: '['x', 'p', 'b']' –

2

Można spróbować następujących Logic

var myArray = ['a', 'x', 'b', 'x', 'x', 'p', 'y', 'x', 'x', 'b', 'x', 'x']; 
 

 
function search(ch, times) { 
 
    var splitStr = ""; 
 
    for(var i = 0; i < times; i++) { 
 
    splitStr += ch; 
 
    } // Generate the split string xx in the above case. 
 
    var str = myArray.join(''); // Join array items into a string 
 
    var array = str.split(splitStr); // Split the string based on split string 
 
    var result = {}; 
 
    // iterate on the array starting from index 1 as at index 0 will be string before split str 
 
    for (var i = 1 ; i < array.length; i++) { 
 
    if(array[i] !== "") { 
 
     result[array[i].substring(0,1)] = ''; // A map in order to avoid duplicate values 
 
    } 
 
    } 
 
    
 
    return Object.keys(result); // return the keys 
 
} 
 

 
console.dir(search('x',2));

2

Można utworzyć dodatkową funkcję isItGood tak:

var myArray = ['a', 'x', 'b', 'x', 'x', 'p', 'y', 'x', 'x', 'b', 'x', 'x']; 
 
var arrLength = myArray.length; 
 
for (var i = 0; i < arrLength; i++) { 
 
    isItGood(myArray, i, 'x', 2); 
 
}; 
 

 
function isItGood(arr, i, elem, total) { 
 
    for (var j = 0 ; j < total ; j++) { 
 
     if (i + total >= arr.length || arr[i+j] != elem) { 
 
      return; 
 
     } 
 
    } 
 
    console.log(arr[i+total]); 
 
    // just to see the result (no need to open a console) 
 
    document.getElementById('p').innerHTML+=("<br/>"+arr[i+total]); 
 
}
<p id="p">Result: </p>

3

A generic proste podejście do każdej porównywalnej zawartości.

function getParts(array, pattern) { 
 
    return array.reduce(function (r, a, i) { 
 
     i >= pattern.length && pattern.every(function (b, j) { 
 
      return b === array[i + j - pattern.length]; 
 
     }) && r.push(a); 
 
     return r; 
 
    }, []); 
 
} 
 

 
function p(o) { 
 
    document.write('<pre>' + JSON.stringify(o, 0, 4) + '</pre>'); 
 
} 
 

 
p(getParts(['a', 'x', 'x', 'x', 'x', 'p', 'y', 'x', 'x', 'b', 'x', 'x'], ['x', 'x'])); 
 
p(getParts(['a', 'x', 'b', 'x', 'x', 'p', 'y', 'x', 'x', 'b', 'x', 'x'], ['a', 'x', 'b'])); 
 
p(getParts(['a', 'b', 'c', 'd', 'z', 'y', 'a', 'b', 'c', 'd', 'x', 'x'], ['a', 'b', 'c', 'd'])); 
 
p(getParts([41, 23, 3, 7, 8, 11, 56, 33, 7, 8, 11, 2, 5], [7, 8, 11]));

2

Oto proste rozwiązanie iteracyjny. Utrzymujemy tablicę consecutive kolejnych elementów. Jeśli tablica osiągnie długość 2, drukowany jest następny element i resetowany jest consecutive.

var arr = ['a', 'x', 'b', 'x', 'x', 'p', 'y', 'x', 'x', 'b', 'x', 'x']; 

var REPEATS_NEEDED = 2; 

var consecutive = [arr[0]]; 
for (var i = 1; i < arr.length; i++) { 
    if (consecutive.length === REPEATS_NEEDED) { 
     console.log(arr[i]); 
     consecutive = [arr[i]]; 
     continue; 
    } 

    // either add to or reset 'consecutive' 
    if (arr[i] === consecutive[0]) { 
     consecutive.push(arr[i]); 
    } else { 
     consecutive = [arr[i]]; 
    } 
}; 
2

Spróbuj użyć for pętlę za pomocą zmiennych przedstawieniu poprzedniego indeksu, aktualny indeks, następny indeks tablicy

var myArray = ["a", "x", "b", "x", "x", "p", "y", "x", "x", "b", "x", "x"]; 
 

 
for (var res = [], curr = 0, prev = curr - 1, match = curr + 1 
 
    ; curr < myArray.length - 1; curr++, prev++, match++) { 
 
    if (myArray[curr] === myArray[prev]) res.push(myArray[match]); 
 
}; 
 

 
console.log(res); 
 
document.body.textContent = res;

2

Gdybym miał napisać to w Scala zamiast JavaScript mogłem po prostu zrób to w jednej linii. myArray.sliding(3).filter(l => l(0) == 'x' && l(1) == 'x').map(l => l(2))

Sądzę, że mógłbym zrobić to samo w JS, jeśli sam wykonam funkcję przesuwną. np.

function sliding(array, n, step) { 
    if(!step) step = 1; 
    var r = []; 
    for(var i = 0; i < array.length - n + 1; i += step) { 
    r.push(array.slice(i, i + n)); 
    } 
    return r; 
} 
var result = sliding(myArray, 3).filter(l => l[0] === "x" && l[1] === "x").map(l => l[2]); 

Jedynym minusem jest to, że działa wolniej niż bardziej iteracyjne podejście. Ale to ma znaczenie tylko dla bardzo dużych tablic.

Powiązane problemy