JavaScript-эквивалентом в C# LINQ для выбора
после этого вопроса здесь:
использование проверенной привязки в нокауте со списком флажков проверяет все флажки
Я создал некоторые флажки с помощью нокаута, которые позволяют выбирать из массива. рабочая скрипка, взятая сверху поста:
есть ли простой способ создания массива только фруктов Документы?
Я больше дома с C#, где я бы сделал что-то вроде selectedFruits.select(fruit=>fruit.id);
есть ли какой-то метод/готовая функция для выполнения чего-то подобного с javascript/jquery? Или самый простой вариант-перебрать список и создать второй массив? Я намерен отправить массив обратно на сервер в JSON, поэтому пытаюсь свести к минимуму отправленные данные.
8 ответов:
да массив.map () или $.map () делает то же самое.
//array.map: var ids = this.fruits.map(function(v){ return v.Id; }); //jQuery.map: var ids2 = $.map(this.fruits, function (v){ return v.Id; }); console.log(ids, ids2);
С массива.карта не поддерживается в старых браузерах, я предлагаю вам придерживаться метод jQuery.
если вы предпочитаете другой по какой-то причине вы всегда можете добавить полифилл для старых поддержку браузера.
вы всегда можете добавлять пользовательские методы в прототип массива ну:
Array.prototype.select = function(expr){ var arr = this; //do custom stuff return arr.map(expr); //or $.map(expr); }; var ids = this.fruits.select(function(v){ return v.Id; });
Расширенная версия, которая использует конструктор функций при передаче строки. Что-то, чтобы поиграть с возможно:
Array.prototype.select = function(expr){ var arr = this; switch(typeof expr){ case 'function': return $.map(arr, expr); break; case 'string': try{ var func = new Function(expr.split('.')[0], 'return ' + expr + ';'); return $.map(arr, func); }catch(e){ return null; } break; default: throw new ReferenceError('expr not defined or not supported'); break; } }; console.log(fruits.select('x.Id'));
обновление:
так как это стало таким популярным ответом, я добавляю аналогичный мой
where()
+firstOrDefault()
. Они также могут быть использованы со строковым подходом конструктора функций (который является самым быстрым), но вот другой подход, использующий объектный литерал в качестве фильтра:Array.prototype.where = function (filter) { var collection = this; switch(typeof filter) { case 'function': return $.grep(collection, filter); case 'object': for(var property in filter) { if(!filter.hasOwnProperty(property)) continue; // ignore inherited properties collection = $.grep(collection, function (item) { return item[property] === filter[property]; }); } return collection.slice(0); // copy the array // (in case of empty object filter) default: throw new TypeError('func must be either a' + 'function or an object of properties and values to filter by'); } }; Array.prototype.firstOrDefault = function(func){ return this.where(func)[0] || null; };
использование:
var persons = [{ name: 'foo', age: 1 }, { name: 'bar', age: 2 }]; // returns an array with one element: var result1 = persons.where({ age: 1, name: 'foo' }); // returns the first matching item in the array, or null if no match var result2 = persons.firstOrDefault({ age: 1, name: 'foo' });
здесь тест jsperf для сравнения конструктора функции и скорости литерала объекта. Если вы решили использовать первый, имейте в виду, чтобы правильно цитировать строки.
мое личное предпочтение заключается в использовании решений на основе литералов объектов при фильтрации 1-2 свойств и передаче функции обратного вызова для более сложной фильтрации.
я закончу это с 2 общими советами при добавлении методов к собственным прототипам объектов:
проверьте наличие существующих методов перед перезаписью, например:
if(!Array.prototype.where) { Array.prototype.where = ...
Если вам не нужно поддерживать IE8 и ниже, определите методы с помощью
Я знаю, что это поздний ответ, но это было полезно для меня! Просто для завершения, используя
$.grep
функция вы можете эмулировать linqwhere()
.Linq:
var maleNames = people .Where(p => p.Sex == "M") .Select(p => p.Name)
Javascript:
// replace where with $.grep // select with $.map var maleNames = $.grep(people, function (p) { return p.Sex == 'M'; }) .map(function (p) { return p.Name; });
так как вы используете нокаут, вы должны рассмотреть возможность использования функции нокаут утилита
arrayMap()
и это другие функции утилиты массива.вот список функций полезности массива и их эквивалентных методов LINQ:
arrayFilter() -> Where() arrayFirst() -> First() arrayForEach() -> (no direct equivalent) arrayGetDistictValues() -> Distinct() arrayIndexOf() -> IndexOf() arrayMap() -> Select() arrayPushAll() -> (no direct equivalent) arrayRemoveItem() -> (no direct equivalent) compareArrays() -> (no direct equivalent)
так что вы могли бы сделать в вашем примере это:
var mapped = ko.utils.arrayMap(selectedFruits, function (fruit) { return fruit.id; });
если вы хотите LINQ как интерфейс в javascript, вы можете использовать библиотеку, такую как linq.js который предлагает хороший интерфейс для многих из LINQ методы.
var mapped = Enumerable.From(selectedFruits) .Select("$.id") // 1 of 3 different ways to specify a selector function .ToArray();
путь ES6:
let people = [{firstName:'Alice',lastName:'Cooper'},{firstName:'Bob',age:'Dylan'}]; let names = Array.from(people, p => p.firstName); for (let name of names) { console.log(name); }
также по адресу:https://jsfiddle.net/52dpucey/
посмотреть подчеркивания.js что обеспечивает много линк как функции. В приведенном примере вы будете использовать функцию map.
Я построил библиотеку Linq для TypeScript под TsLinq.codeplex.com что вы можете использовать для простого javascript тоже. Эта библиотека в 2-3 раза быстрее, чем Linq.js и содержит модульные тесты для всех методов Linq. Может быть, вы могли бы рассмотреть это.
Dinqyjs имеет LINQ-подобный синтаксис и предоставляет полифиллы для таких функций, как map и indexOf, и был разработан специально для работы с массивами в Javascript.