简体   繁体   English

有什么办法可以“加入”两个 8822996504788 arrays 的内容,就像我加入 SQL 一样

[英]Is there some way I can "join" the contents of two javascript arrays much like I would do a join in SQL

I have two arrays: Question and UserProfile我有两个 arrays:Question 和 UserProfile

  • The userProfiles : [] array contain { id, name } objects userProfiles : [] 数组包含{ id, name }对象
  • The questions : [] array contains { id, text, createdBy } objects questions :[] array contains { id, text, createdBy } objects

The createdBy integer in questions is always one of the id values in userProfiles .问题中的createdBy integer 始终是userProfiles中的 id 值之一。

Is there a way I could "join" the arrays in much the same way as I would join up two SQL tables if I was using a database.有没有一种方法可以“加入”arrays,就像我使用数据库时加入两个 SQL 表一样。

What I need as an end result is an array that contains作为最终结果,我需要的是一个包含

{ id, text, name }

Corresponding SQL would be:对应的 SQL 为:

SELECT u.id, q.text, u.name 
FROM userProfiles u 
JOIN questions q ON q.createdBy=u.id

I think what you want is an inner join , which is simple enough to implement in JavaScript:我认为你想要的是一个内部连接,它很简单,可以在 JavaScript 中实现:

const innerJoin = (xs, ys, sel) =>
    xs.reduce((zs, x) =>
    ys.reduce((zs, y) =>        // cartesian product - all combinations
    zs.concat(sel(x, y) || []), // filter out the rows and columns you want
    zs), []);

For the purpose of demonstration we'll use the following data set (thank you @AshokDamani):出于演示目的,我们将使用以下数据集(谢谢@AshokDamani):

const userProfiles = [
    {id: 1, name: "Ashok"},
    {id: 2, name: "Amit"},
    {id: 3, name: "Rajeev"},
];

const questions = [
    {id: 1, text: "text1", createdBy: 2},
    {id: 2, text: "text2", createdBy: 2},
    {id: 3, text: "text3", createdBy: 1},
    {id: 4, text: "text4", createdBy: 2},
    {id: 5, text: "text5", createdBy: 3},
    {id: 6, text: "text6", createdBy: 3},
];

This is how you would use it:这是你将如何使用它:

const result = innerJoin(userProfiles, questions,
    ({id: uid, name}, {id, text, createdBy}) =>
        createdBy === uid && {id, text, name});

In SQL terms this would be similar to:在 SQL 术语中,这类似于:

SELECT questions.id, questions.text, userProfiles.name
FROM userProfiles INNER JOIN questions
ON questions.createdBy = userProfiles.id;

Putting it all together:把它们放在一起:

 const innerJoin = (xs, ys, sel) => xs.reduce((zs, x) => ys.reduce((zs, y) => // cartesian product - all combinations zs.concat(sel(x, y) || []), // filter out the rows and columns you want zs), []); const userProfiles = [ {id: 1, name: "Ashok"}, {id: 2, name: "Amit"}, {id: 3, name: "Rajeev"}, ]; const questions = [ {id: 1, text: "text1", createdBy: 2}, {id: 2, text: "text2", createdBy: 2}, {id: 3, text: "text3", createdBy: 1}, {id: 4, text: "text4", createdBy: 2}, {id: 5, text: "text5", createdBy: 3}, {id: 6, text: "text6", createdBy: 3}, ]; const result = innerJoin(userProfiles, questions, ({id: uid, name}, {id, text, createdBy}) => createdBy === uid && {id, text, name}); console.log("Open your browser console to see the output."); console.table(result);


Edit: However this is not the best solution.编辑:但这不是最好的解决方案。 Since the above solution loops through the Cartesian product it takes O(m × n) time to run.由于上述解决方案循环通过笛卡尔积,因此运行需要O(m × n)时间。 With a little bit of modification we can make it run in O(m + n) time - @pebbl found it first :通过一些修改,我们可以让它在O(m + n)时间内运行 - @pebbl 首先找到它

const equijoin = (xs, ys, primary, foreign, sel) => {
    const ix = xs.reduce((ix, row) => // loop through m items
        ix.set(row[primary], row),    // populate index for primary table
    new Map);                         // create an index for primary table

    return ys.map(row =>              // loop through n items
        sel(ix.get(row[foreign]),     // get corresponding row from primary
        row));                        // select only the columns you need
};

Now you could use it as follows:现在您可以按如下方式使用它:

const result = equijoin(userProfiles, questions, "id", "createdBy",
    ({name}, {id, text}) => ({id, text, name}));

Putting it all together:把它们放在一起:

 const equijoin = (xs, ys, primary, foreign, sel) => { const ix = xs.reduce((ix, row) => ix.set(row[primary], row), new Map); return ys.map(row => sel(ix.get(row[foreign]), row)); }; const userProfiles = [ {id: 1, name: "Ashok"}, {id: 2, name: "Amit"}, {id: 3, name: "Rajeev"}, ]; const questions = [ {id: 1, text: "text1", createdBy: 2}, {id: 2, text: "text2", createdBy: 2}, {id: 3, text: "text3", createdBy: 1}, {id: 4, text: "text4", createdBy: 2}, {id: 5, text: "text5", createdBy: 3}, {id: 6, text: "text6", createdBy: 3}, ]; const result = equijoin(userProfiles, questions, "id", "createdBy", ({name}, {id, text}) => ({id, text, name})); console.log("Open your browser console to see the output."); console.table(result);

This seems to be an important general-purpose question, and although there are many answers, some have borderline behavior like modifying the existing data, solving a completely different problem than the issue at hand, using up to 93,057 bytes of JavaScript (not to mention producing the wrong result), producing overly complex additional nesting of data structures, requiring a lot of code on each invocation, and most seriously, not being a self-contained solution to the important more general-purpose problem at the heart of this question.这似乎是一个重要的通用问题,虽然有很多答案,但有些具有边缘行为,例如修改现有数据,解决与手头问题完全不同的问题,使用高达 93,057 字节的 JavaScript(更不用说产生错误的结果),产生过于复杂的额外数据结构嵌套,每次调用都需要大量代码,最严重的是,它不是解决这个问题核心的更重要的通用问题的独立解决方案。

So for better or for worse, I wrote a shim that extends the JavaScript Array object with a method .joinWith intended to be used in order to join this array of objects with that array of objects, by a common indexing field.因此,无论好坏,我编写了一个 shim,它使用一个方法.joinWith扩展 JavaScript Array对象,该方法旨在by公共索引字段将this对象数组与that对象数组连接起来。 It is possible to select a list of fields desired in output (good for merging arrays of objects with many fields when only a few are wanted) or to omit a list of fields in output (good for merging arrays of objects when most fields are desired but a few are not).可以select输出中所需的字段列表(当只需要几个字段时,适用于合并具有多个字段的对象数组)或omit输出中的字段列表(适用于需要大多数字段时合并对象数组但有一些不是)。

The shim code isn't made to look pretty, so it will be at the end, with the example of how to use it for the OP's particular kind of data coming first:填充代码看起来并不漂亮,所以它会在最后,首先是如何将它用于 OP 的特定类型的数据的示例:

/* this line will produce the array of objects as desired by the OP */
joined_objects_array = userProfiles.joinWith(questions, 'id', ['createdBy'], 'omit');

/* edit: I just want to make 100% sure that this solution works for you, i.e.,
 *       does exactly what you need. I haven't seen your actual data, so it's
 *       possible that your IDs are are not in common, (i.e., your createdBy
 *       is in common like you said, but not the IDs, and if so you could
 *       morph your data first like this:
 * questions.map(function(x) { x.id = x.createdBy; });
 *       before joining the arrays of objects together.
 *
 */

The following code is for demonstration:以下代码用于演示:

var array1 = [{ id: 3124, name: 'Mr. Smith' },
              { id: 710, name: 'Mrs. Jones' }];
var array2 = [{ id: 3124, text: 'wow', createdBy: 'Mr. Jones' },
              { id: 710, text: 'amazing' }];

var results_all = array1.joinWith(array2, 'id');

// [{id:3124, name:"Mr. Smith", text:"wow", createdBy:"Mr. Jones"},
// {id:710, name:"Mrs. Jones", text:"amazing"}]*

var results_selected = array1.joinWith(array2, 'id', ['id', 'text', 'name']);

// [{id:3124, name:"Mr. Smith", text:"wow"},
// {id:710, name:"Mrs. Jones", text:"amazing"}]*

/* or equivalently, */
var results_omitted = array1.joinWith(array2, 'id', ['createdBy'], 1);

// [{id:3124, name:"Mr. Smith", text:"wow"},
// {id:710, name:"Mrs. Jones", text:"amazing"}]*

There are some other nice things this solution does (one of them is preserving the ability to access the resulting data by its indexing key, despite returning an array).这个解决方案还有一些其他的好处(其中之一是保留通过索引键访问结果数据的能力,尽管返回一个数组)。

Enjoy!享受!

/* Array.joinWith - shim by Joseph Myers 7/6/2013 */


if (!Array.prototype.joinWith) {
    +function () {
        Array.prototype.joinWith = function(that, by, select, omit) {
            var together = [], length = 0;
            if (select) select.map(function(x){select[x] = 1;});
            function fields(it) {
                var f = {}, k;
                for (k in it) {
                    if (!select) { f[k] = 1; continue; }
                    if (omit ? !select[k] : select[k]) f[k] = 1;
                }
                return f;
            }
            function add(it) {
                var pkey = '.'+it[by], pobj = {};
                if (!together[pkey]) together[pkey] = pobj,
                    together[length++] = pobj;
                pobj = together[pkey];
                for (var k in fields(it))
                    pobj[k] = it[k];
            }
            this.map(add);
            that.map(add);
            return together;
        }
    }();
}

Documentation:文档:

        /* this and that both refer to an array of objects, each containing
           object[by] as one of their fields */
        /*
         N.B. It is the responsibility of the user of this method
         to ensure that the contents of the [by] fields are
         consistent with each other between the two arrays!
        */
        /* select is an array of field names to be included in the resulting
           objects--all other fields will be excluded, or, if the Boolean value
           of omit evaluates to true, then select is an array of field names to
           be excluded from the resulting objects--all others will be included.
        */

i just about always use underscore.js because it has such good support for arrays and "map reduce" which this problem can be solved with.我几乎总是使用underscore.js,因为它对数组和“map reduce”有很好的支持,可以解决这个问题。

here is a fiddle with a solution for your question ( it assumes there is only one question per user as your original post suggests)这是针对您的问题的解决方案(假设每个用户只有一个问题,正如您的原始帖子所建议的那样)

http://jsfiddle.net/x5Z7f/ http://jsfiddle.net/x5Z7f/

(open the browser console to see the output) (打开浏览器控制台查看输出)

    var userProfiles = [{ id:'1', name:'john' }, { id:'2', name:'mary' }];

var questions =[ { id:'1', text:'question john', createdBy:'1' }, { id:'2', text:'question mary', createdBy:'2' }];

var rows = _.map(userProfiles, function(user){ 
    var question = _.find(questions, function(q){ return q.createdBy == user.id });
    user.text = question? question.text:'';
    return user; 
})

_.each(rows, function(row){ console.log(row) });

the above answer assumes you are using id == createdBy as the joining column.上面的答案假设您使用 id == createdBy 作为连接列。

If it were me, I'd approach this in the following manner:如果是我,我会通过以下方式解决这个问题:

The set-up:设置:

var userProfiles = [], questions = [];

userProfiles.push( {id:1, name:'test'} );
userProfiles.push( {id:2, name:'abc'} );
userProfiles.push( {id:3, name:'def'} );
userProfiles.push( {id:4, name:'ghi'} );

questions.push( {id:1, text:'monkey', createdBy:1} );
questions.push( {id:2, text:'Monkey', createdBy:1} );
questions.push( {id:3, text:'big',    createdBy:2} );
questions.push( {id:4, text:'string', createdBy:2} );
questions.push( {id:5, text:'monKey', createdBy:3} );

First, would be to create a look-up object, where the linking id is used as a key首先,将创建一个查找对象,其中链接 ID 用作键

var createObjectLookup = function( arr, key ){
  var i, l, obj, ret = {};
  for ( i=0, l=arr.length; i<l; i++ ) {
    obj = arr[i];
    ret[obj[key]] = obj;
  }
  return ret;
};

var up = createObjectLookup(userProfiles, 'id');

Now that you have this, it should be easy to step through the questions, and find your user object to merge:现在你有了这个,应该很容易逐步完成问题,并找到要合并的用户对象:

var i, l, question, user, result = [];
for ( i=0, l=questions.length; i<l; i++ ) {
  if ( (question = questions[i]) && (user = up[question.createdBy]) ) {
    result.push({
      id: question.id,
      text: question.text,
      name: user.name
    });
  }
}

You should now have everything you need in result您现在应该拥有所需的一切result

console.log(result);

This is my attempt to make a somehow generic solution.这是我尝试以某种方式制定通用解决方案。 I'm using Array.map and the Array.index methods here:我在这里使用Array.mapArray.index方法:

var arr1 = [
    {id: 1, text:"hello", oid:2},
    {id: 2, text:"juhu", oid:3},
    {id: 3, text:"wohoo", oid:4},
    {id: 4, text:"yeehaw", oid:1}
];
var arr2 = [
    {id: 1, name:"yoda"},
    {id: 2, name:"herbert"},
    {id: 3, name:"john"},
    {id: 4, name:"walter"},
    {id: 5, name:"clint"}
];

function merge(arr1, arr2, prop1, prop2) {
    return arr1.map(function(item){
        var p = item[prop1];
        el = arr2.filter(function(item) {
            return item[prop2] === p;
        });
        if (el.length === 0) {
            return null;
        }
        var res = {};
        for (var i in item) {
            if (i !== prop1) {
                res[i] = item[i];
            }
        }
        for (var i in el[0]) {
            if (i !== prop2) {
                res[i] = el[0][i];
            }
        }
        return res;
    }).filter(function(el){
        return el !== null;
    });
}

var res = merge(arr1, arr2, "oid", "id");
console.log(res);

So basically you can define two arrays and one property for each array, so that prop1 will be replaced with all the properties of an item in array2 whose prop2 is equal to prop1.所以基本上你可以为每个数组定义两个数组和一个属性,这样 prop1 将被替换为 array2 中一个项目的所有属性,其 prop2 等于 prop1。

The result in this case would be:在这种情况下,结果将是:

var res = [
    {id: 1, text:"hello", name:"herbert"},
    {id: 2, text:"juhu", name:"john"},
    {id: 3, text:"wohoo", name:"walter"},
    {id: 4, text:"yeehaw", name:"yoda"}
];

Note that if there is more then one match, the first item will be used and if there is no match, the object will be removed from the resulting array.请注意,如果有多个匹配项,将使用第一个项目,如果没有匹配项,则该对象将从结果数组中删除。

FIDDLE小提琴

all u want is the ResultArray calculated below:你想要的ResultArray下面计算的ResultArray

    var userProfiles1= new Array(1, "ashok");
    var userProfiles2= new Array(2, "amit");
    var userProfiles3= new Array(3, "rajeev");

    var UArray = new Array(userProfiles1, userProfiles2, userProfiles3);

    var questions1= new Array(1, "text1", 2);
    var questions2= new Array(2, "text2", 2);
    var questions3= new Array(3, "text3", 1);
    var questions4= new Array(4, "text4", 2);
    var questions5= new Array(5, "text5", 3);
    var questions6= new Array(6, "text6", 3);

    var QArray = new Array(questions1, questions2, questions3, questions4, questions5, questions6);

    var ResultArray = new Array();

    for (var i=0; i<UArray.length; i++)
    {
        var uid = UArray[i][0];
        var name = UArray[i][1];

        for(var j=0; j<QArray.length; j++)
        {
            if(uid == QArray[j][2])
            {
                 var qid = QArray[j][0]
                 var text = QArray[j][1];

                 ResultArray.push(qid +"," + text +","+ name)
            }
        }    
    }

for(var i=0; i<ResultArray.length; i++)
    {
        document.write(ResultArray[i] + "<br>")
    }

demo : http://jsfiddle.net/VqmVv/演示: http : //jsfiddle.net/VqmVv/

Just wanted to share some generic code:只是想分享一些通用代码:

// Create a cartesian product of the arguments.
// product([1,2],['a','b'],['X']) => [[1,"a","X"],[1,"b","X"],[2,"a","X"],[2,"b","X"]]
// Accepts any number of arguments.
product = function() {
    if(!arguments.length)
        return [[]];
    var p = product.apply(null, [].slice.call(arguments, 1));
    return arguments[0].reduce(function(r, x) {
        return p.reduce(function(r, y) {
            return r.concat([[x].concat(y)]);
        }, r);
    }, []);
}

Your problem:你的问题:

result = product(userProfiles, questions).filter(function(row) {
    return row[0].id == row[1].createdBy;
}).map(function(row) {
    return {
        userName: row[0].name,
        question: row[1].text
    }
})

You can do this using reduce and map .您可以使用reducemap来做到这一点。

First, create a mapping from IDs to names:首先,创建从 ID 到名称的映射:

var id2name = userProfiles.reduce(function(id2name, profile){
    id2name[profile.id] = profile.name;
    return id2name;
}, {});

Second, create a new array of questions but with the name of the user who created the question in place of their ID:其次,创建一个新的问题数组,但使用创建问题的用户名代替他们的 ID:

var qs = questions.map(function(q){
    q.createdByName = id2name[q.createdBy];
    delete q.createdBy;
    return q;
});

A simple way to do the SQL joins in JavaScript:在 JavaScript 中执行SQL 连接的一种简单方法:

 let userProfiles = [ { id: 3, name: "Paquito"}, { id: 2, name: "Jaime" } ]; let questions = [ { id: 22, text: "My question", createdBy: 3 }, { id: 44, text: "Other question", createdBy: 5 } ]; let left_join = questions .map ( q => ({ ...userProfiles.find( u => q.createdBy === u.id ), ...q }) ); document.write("<p>Left join: <br>", JSON.stringify(left_join)); let right_join = userProfiles .map ( u => ({ ...questions.find( q => q.createdBy === u.id ), ...u }) );; document.write("</p><p>Right join: <br>", JSON.stringify(right_join)); let inner_join = questions .filter( q => userProfiles.find( u => q.createdBy === u.id ) ) .map ( q => ({ ...userProfiles.find( u => q.createdBy === u.id ), ...q }) ); document.write("</p><p>Inner join: <br>", JSON.stringify(inner_join));

I don't know any built-in function allowing to do so.我不知道任何允许这样做的内置函数。

You can program your own function, something similar to this jsFiddle :你可以编写自己的函数,类似于这个 jsFiddle

var userProfiles = [{id:1, name:'name1'},{id:2,name:'name2'}];
    var questions = [
        {id:1, text:'text1', createdBy:'foo'},
        {id:1, text:'text2', createdBy:'bar'},
        {id:2, text:'text3', createdBy:'foo'}];

    merged = mergeMyArrays(userProfiles,questions);

    console.log(merged);
    /**
     * This will give you an array like this:
     * [{id:1, name:name1, text:text1}, {...]
     * params : 2 arrays to merge by id
     */
    function mergeMyArrays(u,q){
        var ret = [];
        for(var i = 0, l = u.length; i < l; i++){
            var curU = u[i];
            for(var j = 0, m = q.length; j<m; j++){
                if(q[j].id == curU.id){
                    ret.push({
                        id: curU.id,
                        name: curU.name,
                        text: q[j].text
                    });
                }
            }
        }
        return ret;
    }

Or if you want a better "join" (SQL-y) :或者,如果您想要更好的“加入”(SQL-y):

var userProfiles = [{id:1, name:'name1'},{id:2,name:'name2'}];
var questions = [
    {id:1, text:'text1', createdBy:'foo'},
    {id:1, text:'text2', createdBy:'bar'},
    {id:2, text:'text3', createdBy:'foo'}];

merged = mergeMyArrays(userProfiles,questions);

console.log(merged);
/**
 * This will give you an array like this:
 * [{id:1, name:name1, questions:[{...}]]
 * params : 2 arrays to merge by id
 */
function mergeMyArrays(u,q){
    var ret = [];
    for(var i = 0, l = u.length; i < l; i++){
        var curU = u[i],
            curId = curU.id,
            tmpObj = {id:curId, name:curU.name, questions:[]};
        for(var j = 0, m = q.length; j<m; j++){
            if(q[j].id == curId){
                tmpObj.questions.push({
                    text: q[j].text,
                    createdBy: q[j].createdBy
                });
            }
        }
        ret.push(tmpObj);
    }
    return ret;
}

Like in this jsFiddle就像在这个 jsFiddle

This is easily done with StrelkiJS这很容易用StrelkiJS完成

var userProfiles = new StrelkiJS.IndexedArray();
userProfiles.loadArray([
    {id: 1, name: "Ashok"},
    {id: 2, name: "Amit"},
    {id: 3, name: "Rajeev"}
]);

var questions = new StrelkiJS.IndexedArray();
questions.loadArray([
    {id: 1, text: "text1", createdBy: 2},
    {id: 2, text: "text2", createdBy: 2},
    {id: 3, text: "text3", createdBy: 1},
    {id: 4, text: "text4", createdBy: 2},
    {id: 5, text: "text5", createdBy: 3},
    {id: 6, text: "text6", createdBy: 3}
]);

var res=questions.query([{
    from_col:  "createdBy", 
    to_table:  userProfiles, 
    to_col:    "id", 
    type:      "outer"
}]);

The result will be:结果将是:

[
 [
  {"id":1,"text":"text1","createdBy":2},
  {"id":2,"name":"Amit"}
 ],
 [
  {"id":2,"text":"text2","createdBy":2},
  {"id":2,"name":"Amit"}
 ],
 [
  {"id":3,"text":"text3","createdBy":1},
  {"id":1,"name":"Ashok"}
 ],
 [
  {"id":4,"text":"text4","createdBy":2},
  {"id":2,"name":"Amit"}
 ],
 [
  {"id":5,"text":"text5","createdBy":3},
  {"id":3,"name":"Rajeev"}
 ],
 [
  {"id":6,"text":"text6","createdBy":3},
  {"id":3,"name":"Rajeev"}
 ]
]

Aadit's second O(m+n) solution looked good to me as concise, functional, and efficient. Aadit 的第二个 O(m+n) 解决方案在我看来简洁、实用且高效。 However, it didn't implement the duplication of records when multiple keys match that I needed for my use case, so I wrote this slight variation:但是,当我的用例需要多个键匹配时,它没有实现记录的重复,所以我写了这个轻微的变化:

function equijoin(arrL,arrR,keyL,keyR=keyL){
        const idx = arrL.reduce(
                (idx, objL) => 
                        objL[keyL] === undefined
                        ?idx
                        :idx.set(objL[keyL], [...(idx.get(objL[keyL])||[]), ...[objL]]) 
                ,new Map
            )
        const matches = 
                arrR
                .map(objR =>
                        objR[keyR] === undefined
                        ? []
                        : idx.get(objR[keyR])
                                .map(objL => ({l:objL, r:objR}))
                                .reduce((a,b)=>a.concat(b),[])
                    )
                .reduce((a,b)=>a.concat(b),[])
        return matches
}

(Contrived) Example: (人为的)示例:

var players =[
    {id:"Alice", team:"Red"},
    {id:"Bob", team:"Red"},
    {id:"Clair", team:"Blue"},
    {id:"Dave"},
    {id:"Elliot"}
];

equijoin(players,players,"team")

[
{l:{id:"Alice",team:"Red"},r:{id:"Alice",team:"Red"}},
{l:{id:"Bob",team:"Red"},r:{id:"Alice",team:"Red"}},
{l:{id:"Alice",team:"Red"},r:{id:"Bob",team:"Red"}},
{l:{id:"Bob",team:"Red"},r:{id:"Bob",team:"Red"}},
{l:{id:"Clair",team:"Blue"},r:{id:"Clair",team:"Blue"}}
]

adding to Aadit M Shah's equijoin, there was a request for this to be similar to a left join.添加到 Aadit M Shah 的 equijoin 中,有人要求它类似于左连接。 But as the method isn't a join, but a direct 1 to 1 equals, the method isn't exactly a left join, more a equijoin with a default if no match.但是由于该方法不是连接,而是直接的 1 到 1 等于,所以该方法不完全是左连接,更像是一个等值连接,如果不匹配则使用默认值。 To achieve this however and it make sense reading it, I reversed the method, as it was effectively joining in reverse.然而,为了实现这一点并且阅读它是有意义的,我颠倒了这个方法,因为它实际上是反向加入的。

const equijoinWithDefault = (xs, ys, primary, foreign, sel, def) => {
  const iy = ys.reduce((iy, row) => iy.set(row[foreign], row), new Map);
  return xs.map(row => typeof iy.get(row[primary]) !== 'undefined' ? sel(row, iy.get(row[primary])): sel(row, def));
};

example call:示例调用:

const userProfiles = [
  {id: 1, name: "Ashok"},
  {id: 2, name: "Amit"},
  {id: 3, name: "Rajeev"},
];

const questions2 = [
  {id: 1, text: "text1", createdBy: 2},
  {id: 2, text: "text2", createdBy: 2},
  {id: 3, text: "text3", createdBy: 1},
  {id: 4, text: "text4", createdBy: 2},
  {id: 5, text: "text5", createdBy: 3},
  {id: 6, text: "text6", createdBy: 3},
  {id: 7, text: "text7", createdBy: 4},
];

let result2 = equijoinWithDefault(questions2, userProfiles, "createdBy", "id", ({id, text}, {name}) => ({id, text, name}), {name:null});
Thats another way

var array1 = [{ id: 1, name: 'Khikmat'},
              { id: 2, name: 'User'}];
var array2 = [{ id: 1, text: 'hi test' },
              { id: 2, text: 'amazing test' }, { id: 2, text: 'test'}];
 
 var result = array1.map((elem) => {
   elem["complaints"] = array2.filter((val) => {
       return val.id === elem.id; 
   });
   return elem;
 });

 
console.log(JSON.stringify(result))

A TypeScript version of @aadit-m-shah's answer: @aadit-m-shah 的回答的 TypeScript 版本:

export const equiJoin = <T, U, K>(
    xs: T[],
    ys: U[],
    primaryPredicate: (v: T) => unknown,
    foreignPredicate: (v: U) => unknown,
    selectorFn: (value: T|undefined, row: U) => K) =>
{
    const ix = xs.reduce<Map<unknown, T>>(
        (acc, row) => acc.set(primaryPredicate(row), row),
        new Map
    );
    
    return ys.map((row) => selectorFn(ix.get(foreignPredicate(row)), row));
};

How to use:如何使用:

const userProfiles = [
    {id: 1, name: "Ashok"},
    {id: 2, name: "Amit"},
    {id: 3, name: "Rajeev"},
];

const questions = [
    {id: 1, text: "text1", createdBy: 2},
    {id: 2, text: "text2", createdBy: 2},
    {id: 3, text: "text3", createdBy: 1},
    {id: 4, text: "text4", createdBy: 2},
    {id: 5, text: "text5", createdBy: 3},
    {id: 6, text: "text6", createdBy: 3},
];

const joinedArrays = equiJoin(
    userProfiles,
    questions,
    (profile) => profile.id,
    (q) => q.createdBy,
    (p, {id, text}) => ({ id, text, name: p?.name || 'Unknown' })
);

You can use first jQuery.merge() and then jQuery.unique() to achieve this.您可以先使用 jQuery.merge() 然后使用 jQuery.unique() 来实现这一点。 merge() will add all the items in one array and unique() will remove the duplicates from that array. merge() 将添加一个数组中的所有项目,而 unique() 将从该数组中删除重复项。

http://api.jquery.com/jQuery.merge/ http://api.jquery.com/jQuery.merge/

http://api.jquery.com/jQuery.unique/ http://api.jquery.com/jQuery.unique/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM