获取与多个相同对象不同的javascript对象

时间:2019-06-26 12:57:26

标签: javascript

我有一些如下所示的对象:

one {
      team: "yes",
      school: "yes",
      work: "yes"
     }
two {
      team: "yes",
      school: "yes",
      work: "yes"
     }
three {
      team: "no",
      school: "no",
      work: "yes"
     }
four {
      team: "yes",
      school: "yes",
      work: "yes"
     }     

您可以看到,除三个对象外,所有对象都是相同的。我希望将对象“三个”保存在变量中

var uniqueObject = three;

如何选择与其他对象不同的对象?

5 个答案:

答案 0 :(得分:3)

如果将对象放入数组中,则可以使用数组方法来帮助您实现目标。首先,可以将awaitJSON.stringify()一起使用,以记录在数组中找到的对象数量。然后,您可以将reduceObject.values一起使用,以查找发生.find的对象,这将是您的奇数对象。

请参见以下示例:

1

答案 1 :(得分:1)

首先,我们通过Object.value函数将对象转换为数组。然后,将包含的对象转换为字符串,以允许通过filter进行字符串比较。筛选器检查当前条目是否真正唯一。之后,我们parse将返回的String返回给Object。

截至目前,我们只返回第一个唯一值(以防万一)。但是另一方面,当内部对象具有不同的结构或深层嵌套的结构时,这甚至也可以工作!

let obj = {
  one: {
    team: "yes",
    school: "yes",
    work: "yes"
  },
  two: {
    team: "yes",
    school: "yes",
    work: "yes"
  },
  three: {
    team: "no",
    school: "no",
    work: "yes"
  },
  four: {
    team: "yes",
    school: "yes",
    work: "yes"
  }
};

let res = JSON.parse(Object.values(obj)
            .map(o => JSON.stringify(o))
            .filter((v,i,arr) => arr.indexOf(v) == arr.lastIndexOf(v))[0] || null);

console.log(res)

答案 2 :(得分:1)

我发现这是一个看似有趣的问题。我的第一种方法类似于Nick Parsons的方法,在结果中添加了JSON.parse。但是我不喜欢它返回对象的克隆。我的第二次尝试看起来像这样:

const isNotLikeTheOthers = (makeKey) => (objs) =>  
  objs [Object .entries ( objs.reduce  ( 
    (a, obj, idx, __, key = makeKey(obj)) => ({...a, [key] : [...(a[key] || []), idx]}),
    {}
  )).find (([k, idxs]) => idxs.length == 1)[1][0]]

const oneOfTheseThings = isNotLikeTheOthers (JSON.stringify)

const arr = [{team: "yes", school: "yes", work: "yes"}, {team: "yes", school: "yes", work: "yes"}, {team: "no", school: "no", work: "yes"}, {team: "yes", school: "yes", work: "yes"}];

console .log (
  oneOfTheseThings (arr)
)

我写了一个小的变体,以防项目位于对象而不是数组中。

const isNotLikeTheOthers = (makeKey) => (objs, vals = Object .values (objs) ) =>  
  vals [ Object .entries ( vals .reduce  ( 
    (a, obj, idx, __, key = makeKey(obj)) => ({...a, [key] : [...(a[key] || []), idx]}),
    {}
  )).find (([k, idxs]) => idxs.length == 1)[1][0]]

const oneOfTheseThings = isNotLikeTheOthers (JSON.stringify)

const objs = {one: {team: "yes", school: "yes", work: "yes"}, two: {team: "yes", school: "yes", work: "yes"}, three: {team: "no", school: "no", work: "yes"}, four: {team: "yes", school: "yes", work: "yes"}};

console .log (
  oneOfTheseThings (objs)
) 

这两个都分开makeKey,并使用JSON.stringify。能够提供替代的密钥生成功能可能会很有用。但是在这里内联JSON.stringify也可能有意义。

请注意,这两个都返回对原始对象的引用,而不是对原始对象的克隆,就像我们可能会进行JSON.stringify / JSON.parse舞蹈一样。尽管我不了解OP的要求,但这似乎很有用。

但是,这种方法存在问题。这是find操作。一旦知道结果,它应该能够停止。但是我们必须使用这种技术处理每条记录。我们应该能够创建一个一旦知道结果就停止的版本。那是我第三个版本的起源:

const snowflake = (eq) => ([one, two, three, ...rest]) =>
  eq(one, two) 
    ? [three, ...rest] .find (x => ! eq (one, x))
    : eq (one, three)
      ? two
      : one

const uniqueItem = snowflake (equals)

const arr = [{team: "yes", school: "yes", work: "yes"}, {team: "yes", school: "yes", work: "yes"}, {team: "no", school: "no", work: "yes"}, {team: "yes", school: "yes", work: "yes"}];

console .log (
  uniqueItem (arr)
)
<script src="https://bundle.run/ramda@0.26.1"></script>
<script> const {equals} = ramda               </script>

在这里,我们编写了一个函数,该函数接受一个测试两个值是否相等的函数,并返回一个基于该函数在数组中查找唯一项的函数。在这种情况下,我使用Ramdaequals函数进行测试,但是我们可以像使用Underscore或任何本地版本一样容易地进行测试。实际上,我们还可以通过

使用JSON.stringify的结果比较
const uniqueItem = snowflake ( (a, b) => JSON.stringify (a) == JSON.stringify (b) )

同样,我们可以内联比较操作,除非我强烈需要更通用的版本,否则我可能会这样做。

此版本似乎是最好的版本。这个问题至少要有三个值才有意义,因此我们将它们命名为onetwothree。我们可以从比较前两个项目开始。如果它们相同,则答案是其余项目中的第一项不等于该第一值。如果它们不同,那么其中一个必须是奇数球,我们可以通过比较第一个和第三个来确定哪个。

此版本的时间效率可能不会比其他版本高,尤其是因为像JSON.stringify这样的比较必须对我们的基准对象运行多次。我们可以解决这个问题,并将一个参数加入到equals的某个版本中,但这似乎失去了一些优雅之处。

答案 3 :(得分:0)

您可以使用以下功能对对象进行分组:

function groupObject(object, expression) {
  if (typeof expression !== "function") expression = function(x) {
    return JSON.stringify(x);
  };
  return Object.keys(object).reduce(function(result, key) {
    var groupKey = expression.call(object, object[key], key, object);
    if (!(groupKey in result)) result[groupKey] = {};
    result[groupKey][key] = object[key];
    return result;
  }, {});
}

将获得以下形式的输出:

{
    "{\"team\":\"yes\",\"school\":\"yes\",\"work\":\"yes\"}": {
        "one": {
            "team": "yes",
            "school": "yes",
            "work": "yes"
        },
        "two": {
            "team": "yes",
            "school": "yes",
            "work": "yes"
        },
        "four": {
            "team": "yes",
            "school": "yes",
            "work": "yes"
        }
    },
    "{\"team\":\"no\",\"school\":\"no\",\"work\":\"yes\"}": {
        "three": {
            "team": "no",
            "school": "no",
            "work": "yes"
        }
    }
}

在那之后,您可以找到只有1个项目的组以及该项目的获取名称。

const obj = {
  one: {
    team: "yes",
    school: "yes",
    work: "yes"
  },
  two: {
    team: "yes",
    school: "yes",
    work: "yes"
  },
  three: {
    team: "no",
    school: "no",
    work: "yes"
  },
  four: {
    team: "yes",
    school: "yes",
    work: "yes"
  }
};

function groupObject(object, expression) {
  if (typeof expression !== "function") expression = function(x) {
    return JSON.stringify(x);
  };
  return Object.keys(object).reduce(function(result, key) {
    var groupKey = expression.call(object, object[key], key, object);
    if (!(groupKey in result)) result[groupKey] = {};
    result[groupKey][key] = object[key];
    return result;
  }, {});
}

var group = groupObject(obj);

var groupItem = Object.values(groupObject(obj)).find(function(group) {
  return Object.keys(group).length === 1;
});

var itemName = Object.keys(groupItem)[0];

console.log("Final result: " + itemName);
console.log("Result + object: ");
console.log(groupItem);
console.log("Grouped Object: ");
console.log(group);

为便于记录,上面显示的代码与es-5兼容,并且无需编译器即可在较旧的浏览器中运行。此外,功能groupObject还可以让您更具体(即groupObject(obj, x => x.team)仅将team属性分组):

const obj = {
  one: {
    team: "yes",
    school: "no",
    work: "yes"
  },
  two: {
    team: "yes",
    school: "no",
    work: "yes"
  },
  three: {
    team: "no",
    school: "yes",
    work: "yes"
  },
  four: {
    team: "yes",
    school: "yes",
    work: "yes"
  }
};

function groupObject(object, expression) {
  if (typeof expression !== "function") expression = function(x) {
    return JSON.stringify(x);
  };
  return Object.keys(object).reduce(function(result, key) {
    var groupKey = expression.call(object, object[key], key, object);
    if (!(groupKey in result)) result[groupKey] = {};
    result[groupKey][key] = object[key];
    return result;
  }, {});
}

// `one` and `two` got matched in the first group although they are not identical to `four`, because only the `team` property is being checked
var group = groupObject(obj, x => x.team);

var groupItem = Object.values(groupObject(obj)).find(function(group) {
  return Object.keys(group).length === 1;
});

var itemName = Object.keys(groupItem)[0];

console.log("Final result: " + itemName);
console.log("Result + object: ");
console.log(groupItem);
console.log("Grouped Object: ");
console.log(group);

答案 4 :(得分:0)

这将起作用,希望有帮助。使用Object.values()的简单过滤器,并使用Set带出重复项(以检查其总值是,是还是否)

let js = {
  one: {
    team: "yes",
    school: "yes",
    work: "yes"
  },
  two: {
    team: "yes",
    school: "yes",
    work: "yes"
  },
  three: {
    team: "no",
    school: "no",
    work: "yes"
  },
  four: {
    team: "yes",
    school: "yes",
    work: "yes"
  }
}
// if array length is 1 there are repeated values ,if its 2 then there are two distinct (yes and no both present)
let res = Object.values(js).filter(ele => {
  if ([...new Set(Object.values(ele))].length == 2) {
    return ele;
  }
})

console.log(res[0])