Удалите все значения в строке json из другой строки json [duplicate]

Я создал библиотеку с именем PHPPowertools / DOM-Query , которая позволяет обходить HTML5 и XML-документы так же, как и с jQuery.

Под капотом используется symfony / DomCrawler для преобразования селекторов CSS в селектора XPath .


Использование примера:

namespace PowerTools;

// Get file content
$htmlcode = file_get_contents('https://github.com');

// Define your DOMCrawler based on file string
$H = new DOM_Query($htmlcode);

// Define your DOMCrawler based on an existing DOM_Query instance
$H = new DOM_Query($H->select('body'));

// Passing a string (CSS selector)
$s = $H->select('div.foo');

// Passing an element object (DOM Element)
$s = $H->select($documentBody);

// Passing a DOM Query object
$s = $H->select( $H->select('p + p'));

// Select the body tag
$body = $H->select('body');

// Combine different classes as one selector to get all site blocks
$siteblocks = $body->select('.site-header, .masthead, .site-body, .site-footer');

// Nest your methods just like you would with jQuery
$siteblocks->select('button')->add('span')->addClass('icon icon-printer');

// Use a lambda function to set the text of all site blocks
$siteblocks->text(function( $i, $val) {
    return $i . " - " . $val->attr('class');
});

// Append the following HTML to all site blocks
$siteblocks->append('
'); // Use a descendant selector to select the site's footer $sitefooter = $body->select('.site-footer > .site-center'); // Set some attributes for the site's footer $sitefooter->attr(array('id' => 'aweeesome', 'data-val' => 'see')); // Use a lambda function to set the attributes of all site blocks $siteblocks->attr('data-val', function( $i, $val) { return $i . " - " . $val->attr('class') . " - photo by Kelly Clark"; }); // Select the parent of the site's footer $sitefooterparent = $sitefooter->parent(); // Remove the class of all i-tags within the site's footer's parent $sitefooterparent->select('i')->removeAttr('class'); // Wrap the site's footer within two nex selectors $sitefooter->wrap('
'); [...]

Поддерживаемые методы:


  1. Переименовано 'select' , по понятным причинам
  2. Переименовано 'void', так как 'empty' является зарезервированным словом в PHP

ПРИМЕЧАНИЕ:

Библиотека также включает собственный автозагрузчик с нулевой конфигурацией для совместимых с PSR-0 библиотек. Приведенный пример должен работать из коробки без какой-либо дополнительной настройки. Кроме того, вы можете использовать его с композитором.

54
задан Koop4 20 January 2016 в 17:03
поделиться

12 ответов

Вы можете использовать параметр this для функции filter (), чтобы избежать хранения вашего фильтра в глобальной переменной.

var filtered = [1, 2, 3, 4].filter(
  function(e) {
    return this.indexOf(e) < 0;
  },
  [2, 4]
);
70
ответ дан Gianfranco P. 27 August 2018 в 04:58
поделиться
var array = [1,2,3,4];
var anotherOne = [2,4];
var filteredArray = array.filter(myCallBack);

function myCallBack(el){
  return anotherOne.indexOf(el) < 0;
}

В обратном вызове вы проверяете, находится ли каждое значение array в anotherOne

https://jsfiddle.net/0tsyc1sx/

Если вы используете lodash.js, используйте _.difference

filteredArray = _.difference(array, anotherOne);

Demo

Если у вас есть массив объектов:

var array = [{id :1, name :"test1"},{id :2, name :"test2"},{id :3, name :"test3"},{id :4, name :"test4"}];

var anotherOne = [{id :2, name :"test2"}, {id :4, name :"test4"}];

var filteredArray  = array.filter(function(array_el){
   return anotherOne.filter(function(anotherOne_el){
      return anotherOne_el.id == array_el.id;
   }).length == 0
});

Демо-массив объектов

Demo diff array объектов с lodash

22
ответ дан AshBringer 27 August 2018 в 04:58
поделиться

        /* Here's an example that uses (some) ES6 Javascript semantics to filter an object array by another object array. */

        // x = full dataset
        // y = filter dataset
        let x = [
            {"val": 1, "text": "a"},
            {"val": 2, "text": "b"},
            {"val": 3, "text": "c"},
            {"val": 4, "text": "d"},
            {"val": 5, "text": "e"}
            ],
            y = [
            {"val": 1, "text": "a"},
            {"val": 4, "text": "d"}               
            ];

        // Use map to get a simple array of "val" values. Ex: [1,4]
        let yFilter = y.map(itemY => { return itemY.val; });

        // Use filter and "not" includes to filter the full dataset by the filter dataset's val.
        let filteredX = x.filter(itemX => !yFilter.includes(itemX.val));

        // Print the result.
        console.log(filteredX);

2
ответ дан David Alan Condit 27 August 2018 в 04:58
поделиться

В следующих примерах используется new Set() для создания фильтрованного массива, который имеет только уникальные элементы:

Массив с примитивными типами данных: строка, число, логическое значение, значение null, undefined, symbol:

const a = [1, 2, 3, 4];
const b = [3, 4, 5];
const c = Array.from(new Set(a.concat(b)));

Массив с объектами как элементы:

const a = [{id:1}, {id: 2}, {id: 3}, {id: 4}];
const b = [{id: 3}, {id: 4}, {id: 5}];
const stringifyObject = o => JSON.stringify(o);
const parseString = s => JSON.parse(s);
const c = Array.from(new Set(a.concat(b).map(stringifyObject)), parseString);
1
ответ дан didinko 27 August 2018 в 04:58
поделиться

Вы можете использовать фильтр, а затем для функции фильтра используйте сокращение фильтра, которое проверяет и возвращает true, когда находит совпадение, а затем инвертирует по возврату (!). Функция фильтра вызывается один раз для каждого элемента массива. Вы не выполняете сравнение каких-либо элементов в функции в своем сообщении.

var a1 = [1, 2, 3, 4],
  a2 = [2, 3];

var filtered = a1.filter(function(x) {
  return !a2.reduce(function(y, z) {
    return x == y || x == z || y == true;
  })
});

document.write(filtered);

1
ответ дан Goblinlord 27 August 2018 в 04:58
поделиться

function arr(arr1,arr2){
  
  function filt(value){
    return arr2.indexOf(value) === -1;
    }
  
  return arr1.filter(filt)
  }

document.getElementById("p").innerHTML = arr([1,2,3,4],[2,4])
<p id="p"></p>

0
ответ дан hypemichael 27 August 2018 в 04:58
поделиться

Все вышеперечисленные решения «работают», но менее оптимальны для производительности и все они подходят к проблеме таким же образом, что и линейный поиск всех записей в каждой точке с помощью Array.prototype.indexOf или Array.prototype.includes . Более быстрое решение (гораздо быстрее, чем бинарный поиск в большинстве случаев) - это сортировка массивов и проскальзывание вперед, как вы видите ниже. Однако один недостаток заключается в том, что для этого требуется, чтобы все записи в массиве были числами или строками. Однако, однако, бинарный поиск может в некоторых редких случаях быть быстрее, чем прогрессивный линейный поиск. Эти случаи возникают из-за того, что мой прогрессивный линейный поиск имеет сложность O (2n1 + n2) (только O (n1 + n2) в более быстрой версии C / C ++ ) (где n1 - искомый массив, а n2 - массив фильтров), тогда как бинарный поиск имеет сложность O (n1ceil (log2n2)) (ceil = round up - ceil ing), и, наконец, поиск indexOf имеет весьма переменную сложность между O (n1) и O (n1n2) , усредняя по O (n1ceil (n2 ÷ 2)) . Таким образом, indexOf будет только самым быстрым, в среднем, в случаях (n1, n2) , равных {1,2} , {1,3} или {x, 1 | x∈N} . Тем не менее, это все еще не идеальное представление современного оборудования. IndexOf оптимизирован в максимально возможной степени в большинстве современных браузеров, что делает его очень подверженным законам предсказания ветвей . Таким образом, если мы сделаем такое же предположение на indexOf, как и в случае с прогрессивным линейным и двоичным поиском, - чтобы массив был предварительно настроен, то, согласно статистическим данным, перечисленным в ссылке, мы можем ожидать примерно 6-кратное ускорение для IndexOf, смещение его сложности между O (n1 ÷ 6) и O (n1n2) , усреднение по O (n1ceil (n27 ÷ 12)) , Наконец, обратите внимание, что приведенное ниже решение никогда не будет работать с объектами, потому что невозможно получить внутренний указатель объекта (для численного сравнения) в javascript.

function sortAnyArray(a,b) { return a>b ? 1 : (a===b ? 0 : -1); }
function sortIntArray(a,b) { return a - b; }
var Math_clz32 = Math.clz32;
function filterArrayByAnotherArray(searchArray, filterArray, isInteger = false, i = 0) {
    if (isInteger) { // if all entries in both arrays are integers
        searchArray.sort(sortIntArray);
        filterArray.sort(sortIntArray);
    } else {
        searchArray.sort(sortAnyArray);
        filterArray.sort(sortAnyArray);
    }
    var searchArrayLen = searchArray.length, filterArrayLen = filterArray.length;
    var progressiveLinearComplexity = ((searchArrayLen<<1) + filterArrayLen)>>>0
    var binarySearchComplexity= (searchArrayLen * (32-Math_clz32(filterArrayLen-1)))>>>0;
    // After computing the complexity, we can predict which algorithm will be the fastest
    if (progressiveLinearComplexity < binarySearchComplexity) {
        // Progressive Linear Search
        return searchArray.filter(function(currentValue){
            while (filterArray[i] < currentValue) ++i;
            // +undefined = NaN, which is always false for <, avoiding an infinite loop
            return filterArray[i] !== currentValue;
        });
    } else {
        // Binary Search
        return searchArray.filter(function(currentValue) {
            var lo = -1, hi = filterArrayLen;
            while (1 + lo !== hi) {
                const mi = (hi + lo) >> 1;
                if (currentValue <= filterArray[mi]) hi = mi; else lo = mi;
            }
            return filterArray[hi] !== currentValue;
        });
    }
}

Чтобы доказать разницу в скорости, давайте рассмотрим некоторые JSPerfs. Для фильтрации массива из 16 элементов бинарный поиск примерно на 17% быстрее, чем indexOf, тогда как filterArrayByAnotherArray примерно на 93% быстрее, чем indexOf. Для фильтрации массива из 256 элементов бинарный поиск примерно на 291% быстрее, чем indexOf, тогда как filterArrayByAnotherArray примерно на 353% быстрее, чем indexOf. Для фильтрации массива из 4096 элементов бинарный поиск примерно на 2655% быстрее, чем indexOf, тогда как filterArrayByAnotherArray примерно на 4627% быстрее, чем indexOf.

1
ответ дан Jack Giffin 27 August 2018 в 04:58
поделиться

Вы можете написать общую функцию filterByIndex () и использовать вывод типа в TS, чтобы сохранить проблему с функцией обратного вызова:

, допустим, у вас есть ваш массив [1,2,3,4 ], которые вы хотите отфильтровать () с индексами, указанными в массиве [2,4].

var filtered = [1,2,3,4,].filter(byIndex(element => element, [2,4]))

функция byIndex ожидает функцию элемента и массив и выглядит следующим образом:

Результатом
byIndex = (getter: (e:number) => number, arr: number[]) => (x: number) => {
    var i = getter(x);
    return arr.indexOf(i); 
}

является

filtered = [1,3]
0
ответ дан lama 27 August 2018 в 04:58
поделиться

Вы можете настроить функцию фильтра для итерации по «фильтру».

var arr = [1, 2, 3 ,4 ,5, 6, 7];
var filter = [4, 5, 6];

var filtered = arr.filter(
  function(val) {
    for (var i = 0; i < filter.length; i++) {
      if (val == filter[i]) {
        return false;
      }
    }
    return true;
  }
); 
0
ответ дан metapod 27 August 2018 в 04:58
поделиться

Я бы сделал следующее:

var arr = [1,2,3,4],
    brr = [2,4],
    res = arr.filter(f => !brr.includes(f));
console.log(res);

36
ответ дан Redu 27 August 2018 в 04:58
поделиться

Лучшее описание функции filter - https://developer.mozilla.org/pl/docs/Web/JavaScript/Referencje/Obiekty/Array/filter

] Вы должны просто выполнить функцию:

function conditionFun(element, index, array) {
   return element >= 10;
}
filtered = [12, 5, 8, 130, 44].filter(conditionFun);

И вы не можете получить доступ к значению переменной до его назначения

1
ответ дан suvroc 27 August 2018 в 04:58
поделиться

Более гибкий фильтрующий массив из другого массива, который содержит свойства объекта

function filterFn(array, diffArray, prop, propDiff) {
    diffArray = !propDiff ? diffArray : diffArray.map(d => d[propDiff])
    this.fn = f => diffArray.indexOf(f) === -1
    if (prop) {
         return array.map(r => r[prop]).filter(this.fn)
    } else {
         return array.filter(this.fn)
    }
}

//You can use it like this;

var arr = [];

for (var i = 0; i < 10; i++) {
    var obj = {}
    obj.index = i
    obj.value = Math.pow(2, i)
    arr.push(obj)
}

var arr2 = [1, 2, 3, 4, 5]

var sec = [{t:2}, {t:99}, {t:256}, {t:4096}]

var log = console.log.bind(console)

var filtered = filterFn(arr, sec, 'value', 't')

var filtered2 = filterFn(arr2, sec, null, 't')

log(filtered, filtered2)

1
ответ дан syarul 27 August 2018 в 04:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: