2

Уважаемые StackOverflowers ...Как отобразить и отфильтровать это в стиле точечным бесплатно

У меня есть набор сообщений:

const posts = [ 
    { title: 'post1', tags: ['all', 'half', 'third', 'quarter', 'sixth']}, 
    { title: 'post2', tags: ['all', 'half', 'third', 'quarter', 'sixth']}, 
    { title: 'post3', tags: ['all', 'half', 'third', 'quarter']}, 
    { title: 'post4', tags: ['all', 'half', 'third']}, 
    { title: 'post5', tags: ['all', 'half']}, 
    { title: 'post6', tags: ['all', 'half']}, 
    { title: 'post7', tags: ['all']}, 
    { title: 'post8', tags: ['all']}, 
    { title: 'post9', tags: ['all']}, 
    { title: 'post10', tags: ['all']}, 
    { title: 'post11', tags: ['all']}, 
    { title: 'post12', tags: ['all']} 
]; 

И все большее множество полезных функций:

const map = f => list => list.map(f); 
const filter = f => list => list.filter(f); 
const reduce = f => y => xs => xs.reduce((y,x)=> f(y)(x), y); 
const pipe = (fn,...fns) => (...args) => fns.reduce((acc, f) => f(acc), fn(...args)); 
const comp = (...fns) => pipe(...fns.reverse()); // const comp = (f, g) => x => f(g(x)); 
const prop = prop => obj => obj[prop]; 
const propEq = v => p => obj => prop(p)(obj) === v; 
const flatten = reduce(y=> x=> y.concat(Array.isArray(x) ? flatten (x) : x)) ([]); 
const unique = list => list.filter((v, i, a) => a.indexOf(v) === i); 
const add = a => b => a + b; 
const addO = a => b => Object.assign(a, b); 
const log = x => console.log(x); 

И я хотел бы, чтобы массажировать данные в формате:

[ 
{ title: 'sixth', posts: [array of post objects that all have tag 'sixth'] }, 
{ title: 'quarter', posts: [array of post objects that all have tag 'quarter'] }, 
{ title: 'third', posts: [array of post objects that all have tag ’third'] }, 
etc... 
] 

Использование стиля без точек, используя только многоразовые, компактные служебные функции.

я могу получить уникальные тег из всех сообщений:

const tagsFor = comp(
    unique, 
    flatten, 
    map(prop('tags')) 
); 

tagsFor(posts); 

И я могу работать, как добиться того, что я хочу через карту & фильтра:

tagsFor(posts).map(function(tag) { 
    return { 
    title: tag, 
    posts: posts.filter(function(post) { 
     return post.tags.some(t => t === tag); 
    }); 
    }; 
}); 

Я просто не могу похоже, неловко оглядывается.

Все указатели будут с благодарностью приняты ...

+0

Просто абстрагируйте их в сторону дополнительной функции полезности, и если они не кажутся достаточно обобщенными, отвлечь их дальше. Добавляя к уже установленному набору, вам, по крайней мере, понадобится функция равенства, функция создания объекта и функция удвоения параметра. – Bergi

+0

@Bergi спасибо за ваш вклад. Что такое функция удвоения параметра? – Adam

+1

Что-то вроде 'f => x = f (x) (x)'. Вместе с композицией функций и функцией «флип» вы можете использовать ее для создания «параллельных» потоков данных, например, вам понадобится «tag» (это используется как «title» и «posts»). Или используйте более конкретный комбинатор функций, который выполняет нужную вам работу, в противном случае он становится действительно странным и непригодным для использования. – Bergi

ответ

0

Так со многими благодаря @naomik реструктуризации и @Berghi для меня ведет вниз кролика отверстие комбинаторной логики это то, что я придумал ...

Во-первых, tagsFor собирает все уникальные записи из некоторые вложенные массивы в единый массив, который звучит как базовую функциональность, а не что-то конкретное для какой-либо конкретной проблемы, поэтому я переписал его:

const collectUniq = (p) => comp(// is this what flatMap does? 
    uniq, 
    flatten, 
    map(prop(p)) 
); 

так что, вход @ naomik в мы имеем:

const hasTag = tag => comp( // somePropEq? 
    some(eq(tag)), 
    prop('tags') 
); 


const makeTag = files => tag => ({ 
    title: tag, 
    posts: filter (hasTag(tag)) (files) 
}); 


const buildTags = comp(
    map(makeTag(posts)), 
    collectUniq('tags') 
); 

Проблема для любого молчаливого решения заключается в том, что данные (сообщения) похоронены в makeTag на карте.

SKI исчисление и BCKW логика дает нам полезный набор комбинаторных логических функций, которые я просто оставить здесь:

const I = x => x;      // id 
const B = f => g => x => f(g(x));  // compose <$> 
const K = x => y => x;     // pure 
const C = f => x => y => f(y)(x);  // flip 
const W = f => x => f(x)(x);   // join 
const S = f => g => x => f(x)(g(x)); // sub <*> 

Мы могли ALIAS их к идентификатору, компе, чистый, переворачивать и т.д. но в этом случае я не думаю, что это помогает что-то делать.

Итак, давайте выкопать сообщения с B (сочинить):

const buildTags = comp(
    B(map, makeTag)(posts), 
    collectUniq('tags') 
); 

И теперь мы можем видеть это в виде F (х) (г (х)), где: F = B (map, makeTag); g = collectUniq ('tags'); и х = Сообщения:

const buildTags = S(B(map)(makeTag))(collectUniq('tags')); 

Теперь это молчаливое, декларативные, и легко обращали внимание (на мой взгляд, во всяком случае)

Да, кто-то принесите мне пиво, которое взяло меня за 3 дня! (ouch)

4

я могу видеть влияние некоторых из моих ответов в текущей работе^_^@Bergi дает вам хороший совет, тоже. Просто продолжайте делать общие процедуры и составлять их вместе.

Я просто не могу показаться, что не понимаю, как это сделать в молчаливой манере.

Ну, цель не должна заключаться в том, чтобы идти полностью без точек. Часто вы в конечном итоге сталкиваетесь с действительно странными comp (comp (f)) и comp (f) (comp (g)) вещами, которые действительно трудно получить, когда вы вернетесь к нему позже.

Мы все еще можем сделать пару улучшений с кода Тхо

Это код, который мы меняем

// your original code 
tagsFor(posts).map(function(tag) { 
    return { 
    title: tag, 
    posts: posts.filter(function(post) { 
     return post.tags.some(t => t === tag); 
    }); 
    }; 
}); 

Это обновленный код

// yay 
tagsFor(posts).map(makeTag(posts)); 

// OR 
map (makeTag (posts)) (tagsFor (posts)); 

Вот что utitilies

const comp = f => g => x => f (g (x)); 
const apply = f => x => f (x); 
const eq = x => y => y === x; 
const some = f => xs => xs.some(apply(f)); 
const filter = f => xs => xs.filter(apply(f)); 

const postHasTag = tag => comp (some (eq (tag))) (prop ('tags')); 

const makeTag = posts => tag => ({ 
    title: tag, 
    posts: filter (postHasTag (tag)) (posts) 
}); 

Конечно, это всего лишь один из способов сделать это. Дайте мне знать, если это поможет или у вас возникнут другие вопросы!


«Постоянно увеличивающаяся набор функций полезности»

Это может чувствовать себя подавляющим, чтобы иметь много полезных функций, но вы должны смотреть за некоторые, которые чувствуют себя, как будто вы дублируя поведения.

Возьмите это, например ...

const propEq = v => p => obj => prop(p)(obj) === v; 

3 параметров не означает, что это плохая функция, но она должна по крайней мере, заставит вас дважды подумать об этом, и убедитесь, что они необходимы. Помните, что сложнее создавать функции с большим количеством параметров, поэтому вам следует тщательно обдумать порядок параметров. В любом случае, эта функция propEq должна поднимать красный флаг для вас.

const eq = x => y => y === x; 
const prop = x => y => y[x]; 
const propEq = p => x => comp (eq(x)) (prop(p)) 

После того как вы eq определить как функцию, вы должны быть в состоянии составить его, когда вы сталкиваетесь в ваших других функций в uncomposable ===. Это относится ко всем операторам в JavaScript.

В качестве небольшого вызова ознакомьтесь с вашими reduce, pipe и comp и посмотрите, сможете ли вы удалить пару очков. Если вы застряли, дайте мне знать.

+0

Большое спасибо (снова) за подробный ответ. Мне было много о чем подумать, и мне очень хотелось поиграть. Ваше влияние на мое понимание действительно значительно. Я постараюсь обновить свой вопрос сегодня вечером ... – Adam

Смежные вопросы