D3 v.4 - сравнение значений из нескольких наборов данных

1

(Это переформулировка вопроса, который я не задавал достаточно точно, мои извинения за это).

У меня проблема сравнения данных. У меня есть два набора данных (здесь очень упрощено):

var cat = {
    continents: [
        {
            name:"Africa",
            ab:"AF",
            countries: [
                {name:"Egypt",ab:"Eg"},
                {name:"Niger",ab:"Ng"}
            ]
        },
        {
            name:"America",
            ab:"AM",
            countries: [
                {name:"Brasil",ab:"Br"},
                {name:"Canada",ab:"Ca"},
                {name:"United States",ab:"Us"},
                {name:"Venezuela",ab:"Vz"}
            ]
        },
        {
            name:"Asia",
            ab:"AS",
            countries: [...]
        },
        {
            name:"Europe",
            ab:"EU",
            countries: [
                {name:"France",ab:"Fr"},
                {name:"Germany",ab:"Ge"},
                {name:"Greece",ab:"Gr"},
                {name:"Italy",ab:"It"},
                {name:"United Kingdom",ab:"Uk"}
            ]
        },
        {
            name:"Oceania",
            ab:"OC",
            countries: [...]
        }
    ]
},
{...}

var currentNodes = [
   {name:"Japan",continent:"AS",country:"Jp",x:200,y:50},
   {name:"Italy",continent:"EU",country:"It",x:50,y:400},
   {name:"Bologna",continent:"EU",country:"It",x:180,y:100},
   {name:"Florence",continent:"EU",country:"It",x:50,y:200},
   {name:"Germany",continent:"EU",country:"Ge",x:350,y:430},
   {name:"Canada",continent:"AM",country:"Ca",x:180,y:400}
]

Я пытаюсь получить для каждого континента (и, на втором этапе, каждую страну) значения "ab" при условии, что они присутствуют (как "континент" и "страна") в наборе currentNodes (для того чтобы быть в состоянии их обновить).

Если я правильно понимаю, следующее возвращает все объекты в моем массиве currentNodes:

d3.select('#nav').selectAll('p').data(cat.continents).enter()
    .insert('p').text(function(d) {
        var filteredNodes = currentNodes.filter(function(f) {
            return d.ab == f.continent;
        })
        return filteredNodes;})

- но я не понимаю, почему я не могу выбрать соответствующие значения:

d3.select('#nav').selectAll('p').data(cat.continents).enter()
    .insert('p').text(function(d) {
        var filteredNodes = currentNodes.filter(function(f) {
            return d.ab == f.continent;
        })
        return filteredNodes.ab;})

Я был бы рад за решение, но и понять, что я здесь делаю неправильно. Большое спасибо за вашу помощь - и снисходительность!

Теги:
d3.js

2 ответа

0
Лучший ответ

Посмотрите на свой массив currentNodes. В нем нет свойства, называемого ab. Это свойство cat.continents вместо этого.

Таким образом, если я правильно понимаю, что вы хотите, вы можете сопоставить континенты в массиве currentNodes:

var continentList = currentNodes.map(function(d) {
    return d.continent
}) 

И проверьте, существует ли ab в этом новом массиве:

.text(function(d) {
    return continentList.indexOf(d.ab) > -1 ? d.ab : "not in list";
})

Здесь я использую тернарный оператор и строку "не в списке" для ложного условия.

Вот демо:

var cat = {
  continents: [{
    name: "Africa",
    ab: "AF",
    countries: [{
      name: "Egypt",
      ab: "Eg"
    }, {
      name: "Niger",
      ab: "Ng"
    }]
  }, {
    name: "America",
    ab: "AM",
    countries: [{
      name: "Brasil",
      ab: "Br"
    }, {
      name: "Canada",
      ab: "Ca"
    }, {
      name: "United States",
      ab: "Us"
    }, {
      name: "Venezuela",
      ab: "Vz"
    }]
  }, {
    name: "Asia",
    ab: "AS",
    countries: [{
      name: "Foo",
      ab: "Fo"
    }, {
      name: "Bar",
      ab: "Ba"
    }]
  }, {
    name: "Europe",
    ab: "EU",
    countries: [{
      name: "France",
      ab: "Fr"
    }, {
      name: "Germany",
      ab: "Ge"
    }, {
      name: "Greece",
      ab: "Gr"
    }, {
      name: "Italy",
      ab: "It"
    }, {
      name: "United Kingdom",
      ab: "Uk"
    }]
  }, {
    name: "Oceania",
    ab: "OC",
    countries: [{
      name: "Foo",
      ab: "Fo"
    }, {
      name: "Bar",
      ab: "Ba"
    }]
  }]
};

var currentNodes = [{
  name: "Japan",
  continent: "AS",
  country: "Jp",
  x: 200,
  y: 50
}, {
  name: "Italy",
  continent: "EU",
  country: "It",
  x: 50,
  y: 400
}, {
  name: "Bologna",
  continent: "EU",
  country: "It",
  x: 180,
  y: 100
}, {
  name: "Florence",
  continent: "EU",
  country: "It",
  x: 50,
  y: 200
}, {
  name: "Germany",
  continent: "EU",
  country: "Ge",
  x: 350,
  y: 430
}, {
  name: "Canada",
  continent: "AM",
  country: "Ca",
  x: 180,
  y: 400
}];

var continentList = currentNodes.map(function(d) {
  return d.continent
})

d3.select("body").selectAll(null)
  .data(cat.continents)
  .enter()
  .append('p')
  .text(function(d) {
    return continentList.indexOf(d.ab) > -1 ? d.ab : "not in list";
  })
<script src="//d3js.org/d3.v4.min.js"></script>

Я подозреваю, что вы не хотите показывать континенты "не в списке". В этом случае лучшая идея заключается в фильтрации массива данных перед привязкой данных к элементам (в выборе ввода).

  • 0
    Большое спасибо. Полагаю, что я хотел бы перейти к фильтрации внутри data (), чтобы получить только те элементы, которые относятся к обоим наборам данных. Я пытался это d3.select('body').selectAll('p').data(cat.continents.filter(function(d) { filteredNodes = currentNodes, function(f) { if (d.ab == f.continent) {return d.ab} } return filteredNodes; })) и я не могу понять, почему это не работает.
  • 0
    @Robin Это неправильный синтаксис JS. Вы можете просто сделать это: jsfiddle.net/2a6qxxmx
Показать ещё 2 комментария
0

Во втором примере вы возвращаете массив объектов, которые, как вы надеетесь, будут иметь только один элемент. Поэтому вы должны использовать

return filteredNodes[0].ab

(Конечно, вы не можете получить совпадений или несколько совпадений, если ваши наборы данных не заполнены правильно, поэтому вы можете также добавить некоторые исключения)

  • 0
    Спасибо за помощь. Я пытался, но хотя filteredNodes[0] возвращает соответствующие объекты, filteredNodes[0].ab остается неопределенным. На самом деле я чего-то не понимаю.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню